From 189b9bafbc5b7cf1957c3893e9a44594a056a942 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 13:48:38 +0100 Subject: [PATCH 01/40] Phase 1: codegen falls back to JsonElement instead of object Unmappable / arbitrary-JSON schema nodes now emit JsonElement instead of object in both Generated/SessionEvents.cs and Generated/Rpc.cs. Internal hand-written types that round-trip arbitrary JSON (ToolInvocation.Arguments, ToolResultObject.ToolTelemetry, hook *Input* ToolArgs/ToolResult) are also retyped to JsonElement. Hook *Output* fields, ElicitationSchema.Properties, ElicitationResult.Content, and PermissionRequestResult.Rules remain object- typed to keep consumer-side construction ergonomic; conversion happens at the wire boundary inside the SDK. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Client.cs | 9 +-- dotnet/src/Generated/Rpc.cs | 26 +++---- dotnet/src/Generated/SessionEvents.cs | 38 ++++----- dotnet/src/Session.cs | 77 +++++++++---------- dotnet/src/SessionFsProvider.cs | 22 +++++- dotnet/src/Types.cs | 13 ++-- .../E2E/InMemorySessionFsSqliteHandler.cs | 4 +- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 9 ++- dotnet/test/E2E/RpcMcpConfigE2ETests.cs | 8 +- .../test/E2E/RpcTasksAndHandlersE2ETests.cs | 3 +- dotnet/test/E2E/SessionFsE2ETests.cs | 2 +- dotnet/test/E2E/ToolResultsE2ETests.cs | 6 +- dotnet/test/TestJsonContext.cs | 16 ++++ .../Unit/SessionEventSerializationTests.cs | 2 +- scripts/codegen/csharp.ts | 12 +-- 15 files changed, 137 insertions(+), 110 deletions(-) create mode 100644 dotnet/test/TestJsonContext.cs diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index f314a519b..a42dbbbb6 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -1879,7 +1879,7 @@ public async ValueTask OnSystemMessageTransfo public async ValueTask OnToolCallV2(string sessionId, string toolCallId, string toolName, - object? arguments, + JsonElement? arguments, string? traceparent = null, string? tracestate = null) { @@ -1916,13 +1916,8 @@ public async ValueTask OnToolCallV2(string sessionId, } }; - if (arguments is not null) + if (arguments is JsonElement incomingJsonArgs) { - if (arguments is not JsonElement incomingJsonArgs) - { - throw new InvalidOperationException($"Incoming arguments must be a {nameof(JsonElement)}; received {arguments.GetType().Name}"); - } - foreach (var prop in incomingJsonArgs.EnumerateObject()) { aiFunctionArgs[prop.Name] = prop.Value; diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 2bd4910a2..f60aa7f78 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -247,7 +247,7 @@ public sealed class Tool /// JSON Schema for the tool's input parameters. [JsonPropertyName("parameters")] - public IDictionary? Parameters { get; set; } + public IDictionary? Parameters { get; set; } } /// Built-in tools available for the requested model, with their parameters and instructions. @@ -362,7 +362,7 @@ public sealed class McpConfigList { /// All MCP servers from user config, keyed by name. [JsonPropertyName("servers")] - public IDictionary Servers { get => field ??= new Dictionary(); set; } + public IDictionary Servers { get => field ??= new Dictionary(); set; } } /// MCP server name and configuration to add to user configuration. @@ -370,7 +370,7 @@ internal sealed class McpConfigAddRequest { /// MCP server configuration (stdio process or remote HTTP/SSE). [JsonPropertyName("config")] - public object Config { get; set; } = null!; + public JsonElement Config { get; set; } /// Unique name for the MCP server. [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] @@ -385,7 +385,7 @@ internal sealed class McpConfigUpdateRequest { /// MCP server configuration (stdio process or remote HTTP/SSE). [JsonPropertyName("config")] - public object Config { get; set; } = null!; + public JsonElement Config { get; set; } /// Name of the MCP server to update. [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] @@ -3936,7 +3936,7 @@ internal sealed class HandlePendingToolCallRequest /// Tool call result (string or expanded result object). [JsonPropertyName("result")] - public object? Result { get; set; } + public JsonElement? Result { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] @@ -4353,7 +4353,7 @@ public sealed class UIElicitationResponse /// The form values submitted by the user (present when action is 'accept'). [JsonPropertyName("content")] - public IDictionary? Content { get; set; } + public IDictionary? Content { get; set; } } /// JSON Schema describing the form fields to present to the user. @@ -4362,7 +4362,7 @@ public sealed class UIElicitationSchema { /// Form field definitions, keyed by field name. [JsonPropertyName("properties")] - public IDictionary Properties { get => field ??= new Dictionary(); set; } + public IDictionary Properties { get => field ??= new Dictionary(); set; } /// List of required field names. [JsonPropertyName("required")] @@ -7108,7 +7108,7 @@ public sealed class SessionFsSqliteQueryResult /// For SELECT: array of row objects. For others: empty array. [JsonPropertyName("rows")] - public IList> Rows { get => field ??= []; set; } + public IList> Rows { get => field ??= []; set; } /// Number of rows affected (for INSERT/UPDATE/DELETE). [JsonPropertyName("rowsAffected")] @@ -7120,7 +7120,7 @@ public sealed class SessionFsSqliteQueryRequest { /// Optional named bind parameters. [JsonPropertyName("params")] - public IDictionary? Params { get; set; } + public IDictionary? Params { get; set; } /// SQL query to execute. [JsonPropertyName("query")] @@ -10289,10 +10289,9 @@ public async Task ListAsync(CancellationToken cancellationToken = /// Unique name for the MCP server. /// MCP server configuration (stdio process or remote HTTP/SSE). /// The to monitor for cancellation requests. The default is . - public async Task AddAsync(string name, object config, CancellationToken cancellationToken = default) + public async Task AddAsync(string name, JsonElement config, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(name); - ArgumentNullException.ThrowIfNull(config); var request = new McpConfigAddRequest { Name = name, Config = config }; await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.add", [request], cancellationToken); @@ -10302,10 +10301,9 @@ public async Task AddAsync(string name, object config, CancellationToken cancell /// Name of the MCP server to update. /// MCP server configuration (stdio process or remote HTTP/SSE). /// The to monitor for cancellation requests. The default is . - public async Task UpdateAsync(string name, object config, CancellationToken cancellationToken = default) + public async Task UpdateAsync(string name, JsonElement config, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(name); - ArgumentNullException.ThrowIfNull(config); var request = new McpConfigUpdateRequest { Name = name, Config = config }; await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.update", [request], cancellationToken); @@ -11914,7 +11912,7 @@ internal ToolsApi(CopilotSession session) /// Error message if the tool call failed. /// The to monitor for cancellation requests. The default is . /// Indicates whether the external tool call result was handled successfully. - public async Task HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, CancellationToken cancellationToken = default) + public async Task HandlePendingToolCallAsync(string requestId, JsonElement? result = null, string? error = null, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(requestId); _session.ThrowIfDisposed(); diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index c5a00b5d6..b4b0e7fbd 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -1991,7 +1991,7 @@ public sealed partial class AssistantMessageData /// Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("anthropicAdvisorBlocks")] - public object[]? AnthropicAdvisorBlocks { get; set; } + public JsonElement[]? AnthropicAdvisorBlocks { get; set; } /// Anthropic advisor model ID used for this response, for timeline display on replay. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2260,7 +2260,7 @@ public sealed partial class ToolUserRequestedData /// Arguments for the tool invocation. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public object? Arguments { get; set; } + public JsonElement? Arguments { get; set; } /// Unique identifier for this tool call. [JsonPropertyName("toolCallId")] @@ -2277,7 +2277,7 @@ public sealed partial class ToolExecutionStartData /// Arguments passed to the tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public object? Arguments { get; set; } + public JsonElement? Arguments { get; set; } /// Name of the MCP server hosting this tool, when the tool is an MCP tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2380,7 +2380,7 @@ public sealed partial class ToolExecutionCompleteData /// Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolTelemetry")] - public IDictionary? ToolTelemetry { get; set; } + public IDictionary? ToolTelemetry { get; set; } /// Identifier for the agent loop turn this tool was invoked in, matching the corresponding assistant.turn_start event. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2562,7 +2562,7 @@ public sealed partial class HookStartData /// Input data passed to the hook. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("input")] - public object? Input { get; set; } + public JsonElement? Input { get; set; } } /// Hook invocation completion details including output, success status, and error information. @@ -2584,7 +2584,7 @@ public sealed partial class HookEndData /// Output data produced by the hook. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("output")] - public object? Output { get; set; } + public JsonElement? Output { get; set; } /// Whether the hook completed successfully. [JsonPropertyName("success")] @@ -2757,7 +2757,7 @@ public sealed partial class ElicitationCompletedData /// The submitted form data when action is 'accept'; keys match the requested schema fields. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("content")] - public IDictionary? Content { get; set; } + public IDictionary? Content { get; set; } /// Request ID of the resolved elicitation request; clients should dismiss any UI for this request. [JsonPropertyName("requestId")] @@ -2769,7 +2769,7 @@ public sealed partial class SamplingRequestedData { /// The JSON-RPC request ID from the MCP protocol. [JsonPropertyName("mcpRequestId")] - public required object McpRequestId { get; set; } + public required JsonElement McpRequestId { get; set; } /// Unique identifier for this sampling request; used to respond via session.respondToSampling(). [JsonPropertyName("requestId")] @@ -2830,7 +2830,7 @@ public sealed partial class SessionCustomNotificationData /// Source-defined JSON payload for the custom notification. [JsonPropertyName("payload")] - public required object Payload { get; set; } + public required JsonElement Payload { get; set; } /// Namespace for the custom notification producer. [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] @@ -2855,7 +2855,7 @@ public sealed partial class ExternalToolRequestedData /// Arguments to pass to the external tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public object? Arguments { get; set; } + public JsonElement? Arguments { get; set; } /// Unique identifier for this request; used to respond via session.respondToExternalTool(). [JsonPropertyName("requestId")] @@ -3525,7 +3525,7 @@ public sealed partial class AssistantMessageToolRequest /// Arguments to pass to the tool, format depends on the tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public object? Arguments { get; set; } + public JsonElement? Arguments { get; set; } /// Resolved intention summary describing what this specific call does. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3983,7 +3983,7 @@ public sealed partial class SystemMessageMetadata /// Template variables used when constructing the prompt. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("variables")] - public IDictionary? Variables { get; set; } + public IDictionary? Variables { get; set; } } /// Schema for the `SystemNotificationAgentCompleted` type. @@ -4289,7 +4289,7 @@ public sealed partial class PermissionRequestMcp : PermissionRequest /// Arguments to pass to the MCP tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public object? Args { get; set; } + public JsonElement? Args { get; set; } /// Whether this MCP tool is read-only (no side effects). [JsonPropertyName("readOnly")] @@ -4391,7 +4391,7 @@ public sealed partial class PermissionRequestCustomTool : PermissionRequest /// Arguments to pass to the custom tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public object? Args { get; set; } + public JsonElement? Args { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4423,7 +4423,7 @@ public sealed partial class PermissionRequestHook : PermissionRequest /// Arguments of the tool call being gated. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolArgs")] - public object? ToolArgs { get; set; } + public JsonElement? ToolArgs { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4606,7 +4606,7 @@ public sealed partial class PermissionPromptRequestMcp : PermissionPromptRequest /// Arguments to pass to the MCP tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public object? Args { get; set; } + public JsonElement? Args { get; set; } /// Name of the MCP server providing the tool. [JsonPropertyName("serverName")] @@ -4704,7 +4704,7 @@ public sealed partial class PermissionPromptRequestCustomTool : PermissionPrompt /// Arguments to pass to the custom tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public object? Args { get; set; } + public JsonElement? Args { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4758,7 +4758,7 @@ public sealed partial class PermissionPromptRequestHook : PermissionPromptReques /// Arguments of the tool call being gated. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolArgs")] - public object? ToolArgs { get; set; } + public JsonElement? ToolArgs { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -5128,7 +5128,7 @@ public sealed partial class ElicitationRequestedSchema { /// Form field definitions, keyed by field name. [JsonPropertyName("properties")] - public required IDictionary Properties { get; set; } + public required IDictionary Properties { get; set; } /// List of required field names. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 1ca9eb621..ffbd2fa21 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -601,7 +601,7 @@ private async Task HandleBroadcastEventAsync(SessionEvent sessionEvent) ? new ElicitationSchema { Type = data.RequestedSchema.Type, - Properties = data.RequestedSchema.Properties, + Properties = data.RequestedSchema.Properties.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value), Required = data.RequestedSchema.Required?.ToList() } : null; @@ -651,7 +651,7 @@ await HandleElicitationRequestAsync( /// /// Executes a tool handler and sends the result back via the HandlePendingToolCall RPC. /// - private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, string toolCallId, object? arguments, AIFunction tool) + private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, string toolCallId, JsonElement? arguments, AIFunction tool) { try { @@ -671,13 +671,8 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, } }; - if (arguments is not null) + if (arguments is JsonElement incomingJsonArgs) { - if (arguments is not JsonElement incomingJsonArgs) - { - throw new InvalidOperationException($"Incoming arguments must be a {nameof(JsonElement)}; received {arguments.GetType().Name}"); - } - foreach (var prop in incomingJsonArgs.EnumerateObject()) { aiFunctionArgs[prop.Name] = prop.Value; @@ -695,9 +690,10 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, toolName); var toolResultObject = ToolResultObject.ConvertFromInvocationResult(result, tool.JsonSerializerOptions); + var toolResultJson = JsonSerializer.SerializeToElement(toolResultObject, TypesJsonContext.Default.ToolResultObject); var responseRpcTimestamp = Stopwatch.GetTimestamp(); - await Rpc.Tools.HandlePendingToolCallAsync(requestId, toolResultObject, error: null); + await Rpc.Tools.HandlePendingToolCallAsync(requestId, toolResultJson, error: null); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, "CopilotSession.ExecuteToolAndRespondAsync response sent successfully. Elapsed={Elapsed}, SessionId={SessionId}, RequestId={RequestId}, ToolCallId={ToolCallId}, Tool={ToolName}", responseRpcTimestamp, @@ -915,7 +911,9 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UIElicitationResponse { Action = result.Action, - Content = result.Content + Content = result.Content?.ToDictionary( + kvp => kvp.Key, + kvp => JsonSerializer.SerializeToElement(kvp.Value, TypesJsonContext.Default.Object)) }); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, "CopilotSession.HandleElicitationRequestAsync response sent successfully. Elapsed={Elapsed}, SessionId={SessionId}, RequestId={RequestId}", @@ -967,12 +965,18 @@ public async Task ElicitationAsync(ElicitationParams elicitat var schema = new UIElicitationSchema { Type = elicitationParams.RequestedSchema.Type, - Properties = elicitationParams.RequestedSchema.Properties, + Properties = elicitationParams.RequestedSchema.Properties.ToDictionary( + kvp => kvp.Key, + kvp => JsonSerializer.SerializeToElement(kvp.Value, TypesJsonContext.Default.Object)), Required = elicitationParams.RequestedSchema.Required }; var result = await session.Rpc.Ui.ElicitationAsync(elicitationParams.Message, schema, cancellationToken); - return new ElicitationResult { Action = result.Action, Content = result.Content }; + return new ElicitationResult + { + Action = result.Action, + Content = result.Content?.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value) + }; } public async Task ConfirmAsync(string message, CancellationToken cancellationToken) @@ -984,9 +988,9 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat var schema = new UIElicitationSchema { Type = "object", - Properties = new Dictionary + Properties = new Dictionary { - ["confirmed"] = new Dictionary { ["type"] = "boolean", ["default"] = true } + ["confirmed"] = JsonDocument.Parse("""{"type":"boolean","default":true}""").RootElement.Clone() }, Required = ["confirmed"] }; @@ -996,11 +1000,10 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat && result.Content != null && result.Content.TryGetValue("confirmed", out var val)) { - return val switch + return val.ValueKind switch { - bool b => b, - JsonElement { ValueKind: JsonValueKind.True } => true, - JsonElement { ValueKind: JsonValueKind.False } => false, + JsonValueKind.True => true, + JsonValueKind.False => false, _ => false }; } @@ -1015,12 +1018,13 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat session.ThrowIfDisposed(); session.AssertElicitation(); + var enumJson = JsonSerializer.Serialize(options, TypesJsonContext.Default.StringArray); var schema = new UIElicitationSchema { Type = "object", - Properties = new Dictionary + Properties = new Dictionary { - ["selection"] = new Dictionary { ["type"] = "string", ["enum"] = options } + ["selection"] = JsonDocument.Parse($$"""{"type":"string","enum":{{enumJson}}}""").RootElement.Clone() }, Required = ["selection"] }; @@ -1030,12 +1034,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat && result.Content != null && result.Content.TryGetValue("selection", out var val)) { - return val switch - { - string s => s, - JsonElement { ValueKind: JsonValueKind.String } je => je.GetString(), - _ => val.ToString() - }; + return val.ValueKind == JsonValueKind.String ? val.GetString() : val.ToString(); } return null; @@ -1047,18 +1046,21 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat session.ThrowIfDisposed(); session.AssertElicitation(); - var field = new Dictionary { ["type"] = "string" }; - if (options?.Title != null) field["title"] = options.Title; - if (options?.Description != null) field["description"] = options.Description; - if (options?.MinLength != null) field["minLength"] = options.MinLength; - if (options?.MaxLength != null) field["maxLength"] = options.MaxLength; - if (options?.Format != null) field["format"] = options.Format; - if (options?.Default != null) field["default"] = options.Default; + var fieldNode = new System.Text.Json.Nodes.JsonObject { ["type"] = "string" }; + if (options?.Title != null) fieldNode["title"] = options.Title; + if (options?.Description != null) fieldNode["description"] = options.Description; + if (options?.MinLength != null) fieldNode["minLength"] = options.MinLength; + if (options?.MaxLength != null) fieldNode["maxLength"] = options.MaxLength; + if (options?.Format != null) fieldNode["format"] = options.Format; + if (options?.Default != null) fieldNode["default"] = options.Default; var schema = new UIElicitationSchema { Type = "object", - Properties = new Dictionary { ["value"] = field }, + Properties = new Dictionary + { + ["value"] = JsonDocument.Parse(fieldNode.ToJsonString()).RootElement.Clone() + }, Required = ["value"] }; @@ -1067,12 +1069,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat && result.Content != null && result.Content.TryGetValue("value", out var val)) { - return val switch - { - string s => s, - JsonElement { ValueKind: JsonValueKind.String } je => je.GetString(), - _ => val.ToString() - }; + return val.ValueKind == JsonValueKind.String ? val.GetString() : val.ToString(); } return null; diff --git a/dotnet/src/SessionFsProvider.cs b/dotnet/src/SessionFsProvider.cs index 3e3638c83..ef7845a31 100644 --- a/dotnet/src/SessionFsProvider.cs +++ b/dotnet/src/SessionFsProvider.cs @@ -3,6 +3,7 @@ *--------------------------------------------------------------------------------------------*/ using GitHub.Copilot.SDK.Rpc; +using System.Text.Json; namespace GitHub.Copilot.SDK; @@ -44,7 +45,7 @@ public interface ISessionFsSqliteProvider Task QueryAsync( SessionFsSqliteQueryType queryType, string query, - IDictionary? bindParams, + IDictionary? bindParams, CancellationToken cancellationToken); /// @@ -287,11 +288,16 @@ async Task ISessionFsHandler.SqliteQueryAsync(Sessio try { - var result = await sqliteProvider.QueryAsync(request.QueryType, request.Query, request.Params, cancellationToken).ConfigureAwait(false); + var bindParams = request.Params?.ToDictionary( + kvp => kvp.Key, + kvp => JsonElementToValue(kvp.Value)); + var result = await sqliteProvider.QueryAsync(request.QueryType, request.Query, bindParams, cancellationToken).ConfigureAwait(false); return new SessionFsSqliteQueryResult { - Rows = result?.Rows ?? [], + Rows = result?.Rows?.Select(row => (IDictionary)row.ToDictionary( + kvp => kvp.Key, + kvp => JsonSerializer.SerializeToElement(kvp.Value, TypesJsonContext.Default.Object))).ToList() ?? [], Columns = result?.Columns ?? [], RowsAffected = result?.RowsAffected ?? 0, LastInsertRowid = result?.LastInsertRowid, @@ -329,4 +335,14 @@ private static SessionFsError ToSessionFsError(Exception ex) : SessionFsErrorCode.UNKNOWN; return new SessionFsError { Code = code, Message = ex.Message }; } + + private static object? JsonElementToValue(JsonElement element) => element.ValueKind switch + { + JsonValueKind.Null => null, + JsonValueKind.True => true, + JsonValueKind.False => false, + JsonValueKind.String => element.GetString(), + JsonValueKind.Number => element.TryGetInt64(out var l) ? l : element.GetDouble(), + _ => element.GetRawText(), + }; } diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 99e2f142d..0cf559a8c 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -407,7 +407,7 @@ public class ToolResultObject /// Custom telemetry data associated with the tool execution. /// [JsonPropertyName("toolTelemetry")] - public IDictionary? ToolTelemetry { get; set; } + public IDictionary? ToolTelemetry { get; set; } /// /// Converts the result of an invocation into a @@ -519,7 +519,7 @@ public class ToolInvocation /// /// Arguments passed to the tool by the language model. /// - public object? Arguments { get; set; } + public JsonElement? Arguments { get; set; } } /// @@ -1116,7 +1116,7 @@ public class PreToolUseHookInput /// Arguments that will be passed to the tool. /// [JsonPropertyName("toolArgs")] - public object? ToolArgs { get; set; } + public JsonElement? ToolArgs { get; set; } } /// @@ -1198,13 +1198,13 @@ public class PostToolUseHookInput /// Arguments that were passed to the tool. /// [JsonPropertyName("toolArgs")] - public object? ToolArgs { get; set; } + public JsonElement? ToolArgs { get; set; } /// /// Result returned by the tool execution. /// [JsonPropertyName("toolResult")] - public object? ToolResult { get; set; } + public JsonElement? ToolResult { get; set; } } /// @@ -3186,4 +3186,7 @@ public class SystemMessageTransformRpcResponse [JsonSerializable(typeof(ToolResultObject))] [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(JsonElement?))] +[JsonSerializable(typeof(object))] +[JsonSerializable(typeof(Dictionary))] +[JsonSerializable(typeof(string[]))] internal partial class TypesJsonContext : JsonSerializerContext; diff --git a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs index 2bfc4b1d8..cdf5f5205 100644 --- a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs +++ b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs @@ -43,7 +43,7 @@ private SqliteConnection GetOrCreateDb() public Task QueryAsync( SessionFsSqliteQueryType queryType, string query, - IDictionary? bindParams, + IDictionary? bindParams, CancellationToken cancellationToken) { sqliteCalls.Add(new SqliteCall(sessionId, queryType.Value, query)); @@ -125,7 +125,7 @@ public Task ExistsAsync(CancellationToken cancellationToken) return Task.FromResult(_db is not null); } - private static void AddParams(SqliteCommand cmd, IDictionary? bindParams) + private static void AddParams(SqliteCommand cmd, IDictionary? bindParams) { if (bindParams is null) return; foreach (var (key, value) in bindParams) diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index f78ba0d70..fdb030f7f 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -5,6 +5,7 @@ using GitHub.Copilot.SDK.Test.Harness; using Microsoft.Extensions.AI; using System.ComponentModel; +using System.Text.Json; using Xunit; using Xunit.Abstractions; using RpcPermissionDecisionApproveOnce = GitHub.Copilot.SDK.Rpc.PermissionDecisionApproveOnce; @@ -141,7 +142,7 @@ await session1.SendAsync(new MessageOptions var toolResult = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolEvent.Data.RequestId, - result: "EXTERNAL_RESUMED_BETA"); + result: JsonDocument.Parse("\"EXTERNAL_RESUMED_BETA\"").RootElement.Clone()); Assert.True(toolResult.Success); var answer = await TestHelper.GetFinalAssistantMessageAsync(session2, PendingWorkTimeout); @@ -210,7 +211,7 @@ await session1.SendAsync(new MessageOptions var resumedResult = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolEvent.Data.RequestId, - result: "EXTERNAL_RESUMED_BETA"); + result: JsonDocument.Parse("\"EXTERNAL_RESUMED_BETA\"").RootElement.Clone()); Assert.True(resumedResult.Success); // continuePendingWork=false may interrupt agent continuation before this response, @@ -287,11 +288,11 @@ await Task.WhenAll( var toolB = toolEvents["pending_lookup_b"]; var resultB = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolB.Data.RequestId, - result: "PARALLEL_B_BETA"); + result: JsonDocument.Parse("\"PARALLEL_B_BETA\"").RootElement.Clone()); Assert.True(resultB.Success); var resultA = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolA.Data.RequestId, - result: "PARALLEL_A_ALPHA"); + result: JsonDocument.Parse("\"PARALLEL_A_ALPHA\"").RootElement.Clone()); Assert.True(resultA.Success); await session2.DisposeAsync(); diff --git a/dotnet/test/E2E/RpcMcpConfigE2ETests.cs b/dotnet/test/E2E/RpcMcpConfigE2ETests.cs index 179fc4828..87ccc5335 100644 --- a/dotnet/test/E2E/RpcMcpConfigE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpConfigE2ETests.cs @@ -34,11 +34,11 @@ public async Task Should_Call_Server_Mcp_Config_Rpcs() try { - await Client.Rpc.Mcp.Config.AddAsync(serverName, config); + await Client.Rpc.Mcp.Config.AddAsync(serverName, JsonSerializer.SerializeToElement(config, TestSharedJsonContext.Default.DictionaryStringObject)); var afterAdd = await Client.Rpc.Mcp.Config.ListAsync(); Assert.Contains(serverName, afterAdd.Servers.Keys); - await Client.Rpc.Mcp.Config.UpdateAsync(serverName, updatedConfig); + await Client.Rpc.Mcp.Config.UpdateAsync(serverName, JsonSerializer.SerializeToElement(updatedConfig, TestSharedJsonContext.Default.DictionaryStringObject)); var afterUpdate = await Client.Rpc.Mcp.Config.ListAsync(); var updated = GetServerConfig(afterUpdate, serverName); Assert.Equal("node", updated.GetProperty("command").GetString()); @@ -84,7 +84,7 @@ public async Task Should_RoundTrip_Http_Mcp_Oauth_Config_Rpc() try { - await Client.Rpc.Mcp.Config.AddAsync(serverName, config); + await Client.Rpc.Mcp.Config.AddAsync(serverName, JsonSerializer.SerializeToElement(config, TestSharedJsonContext.Default.McpServerConfig)); var afterAdd = await Client.Rpc.Mcp.Config.ListAsync(); var added = GetServerConfig(afterAdd, serverName); Assert.Equal("http", added.GetProperty("type").GetString()); @@ -94,7 +94,7 @@ public async Task Should_RoundTrip_Http_Mcp_Oauth_Config_Rpc() Assert.False(added.GetProperty("oauthPublicClient").GetBoolean()); Assert.Equal("client_credentials", added.GetProperty("oauthGrantType").GetString()); - await Client.Rpc.Mcp.Config.UpdateAsync(serverName, updatedConfig); + await Client.Rpc.Mcp.Config.UpdateAsync(serverName, JsonSerializer.SerializeToElement(updatedConfig, TestSharedJsonContext.Default.McpServerConfig)); var afterUpdate = await Client.Rpc.Mcp.Config.ListAsync(); var updated = GetServerConfig(afterUpdate, serverName); Assert.Equal("https://example.com/updated-mcp", updated.GetProperty("url").GetString()); diff --git a/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs b/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs index 6e8860964..0813ac981 100644 --- a/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs +++ b/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs @@ -4,6 +4,7 @@ using GitHub.Copilot.SDK.Rpc; using GitHub.Copilot.SDK.Test.Harness; +using System.Text.Json; using Xunit; using Xunit.Abstractions; @@ -143,7 +144,7 @@ public async Task Should_Return_Expected_Results_For_Missing_Pending_Handler_Req var tool = await session.Rpc.Tools.HandlePendingToolCallAsync( requestId: "missing-tool-request", - result: "tool result"); + result: JsonDocument.Parse("\"tool result\"").RootElement.Clone()); Assert.False(tool.Success); var command = await session.Rpc.Commands.HandlePendingCommandAsync( diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index 7649c160c..3a5a03cf0 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -608,7 +608,7 @@ protected override Task RmAsync(string path, bool recursive, bool force, Cancell protected override Task RenameAsync(string src, string dest, CancellationToken cancellationToken) => Task.FromException(exception); - Task ISessionFsSqliteProvider.QueryAsync(SessionFsSqliteQueryType queryType, string query, IDictionary? bindParams, CancellationToken cancellationToken) => + Task ISessionFsSqliteProvider.QueryAsync(SessionFsSqliteQueryType queryType, string query, IDictionary? bindParams, CancellationToken cancellationToken) => Task.FromException(exception); Task ISessionFsSqliteProvider.ExistsAsync(CancellationToken cancellationToken) => diff --git a/dotnet/test/E2E/ToolResultsE2ETests.cs b/dotnet/test/E2E/ToolResultsE2ETests.cs index c1283baa5..ae2454a64 100644 --- a/dotnet/test/E2E/ToolResultsE2ETests.cs +++ b/dotnet/test/E2E/ToolResultsE2ETests.cs @@ -111,10 +111,10 @@ static ToolResultAIContent AnalyzeCode([Description("File to analyze")] string f { TextResultForLlm = $"Analysis of {file}: no issues found", ResultType = "success", - ToolTelemetry = new Dictionary + ToolTelemetry = new Dictionary { - ["metrics"] = new Dictionary { ["analysisTimeMs"] = 150 }, - ["properties"] = new Dictionary { ["analyzer"] = "eslint" }, + ["metrics"] = JsonDocument.Parse("""{"analysisTimeMs":150}""").RootElement.Clone(), + ["properties"] = JsonDocument.Parse("""{"analyzer":"eslint"}""").RootElement.Clone(), }, }); } diff --git a/dotnet/test/TestJsonContext.cs b/dotnet/test/TestJsonContext.cs new file mode 100644 index 000000000..cb41df2a1 --- /dev/null +++ b/dotnet/test/TestJsonContext.cs @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +using System.Text.Json.Serialization; + +namespace GitHub.Copilot.SDK.Test; + +[JsonSourceGenerationOptions(System.Text.Json.JsonSerializerDefaults.Web)] +[JsonSerializable(typeof(string[]))] +[JsonSerializable(typeof(Dictionary))] +[JsonSerializable(typeof(Dictionary))] +[JsonSerializable(typeof(McpServerConfig))] +[JsonSerializable(typeof(McpHttpServerConfig))] +[JsonSerializable(typeof(McpStdioServerConfig))] +internal partial class TestSharedJsonContext : JsonSerializerContext; diff --git a/dotnet/test/Unit/SessionEventSerializationTests.cs b/dotnet/test/Unit/SessionEventSerializationTests.cs index 3622821dc..6f009fcdf 100644 --- a/dotnet/test/Unit/SessionEventSerializationTests.cs +++ b/dotnet/test/Unit/SessionEventSerializationTests.cs @@ -66,7 +66,7 @@ public class SessionEventSerializationTests Content = "ok", DetailedContent = "ok", }, - ToolTelemetry = new Dictionary + ToolTelemetry = new Dictionary { ["properties"] = ParseJsonElement("""{"command":"view"}"""), ["metrics"] = ParseJsonElement("""{"resultLength":2}"""), diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 8fd6b6f58..9ea3c07d8 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -275,6 +275,7 @@ function isNonNullableCSharpValueType(typeName: string): boolean { "long", "DateTimeOffset", "TimeSpan", + "JsonElement", ].includes(typeName) || generatedEnums.has(typeName) || emittedRpcEnumResultTypes.has(typeName) || externalRpcValueTypes.has(typeName); } @@ -361,7 +362,7 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: if (type === "boolean") return required ? "bool" : "bool?"; if (type === "array") { const items = schema.items as JSONSchema7 | undefined; - const itemType = items ? schemaTypeToCSharp(items, true, knownTypes) : "object"; + const itemType = items ? schemaTypeToCSharp(items, true, knownTypes) : "JsonElement"; return required ? `${itemType}[]` : `${itemType}[]?`; } if (type === "object") { @@ -369,9 +370,9 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: const valueType = schemaTypeToCSharp(schema.additionalProperties as JSONSchema7, true, knownTypes); return required ? `IDictionary` : `IDictionary?`; } - return required ? "object" : "object?"; + return required ? "JsonElement" : "JsonElement?"; } - return required ? "object" : "object?"; + return required ? "JsonElement" : "JsonElement?"; } /** Tracks whether any TimeSpan property was emitted so the converter can be generated. */ @@ -1145,12 +1146,12 @@ function resolveSessionPropertyType( } const unionType = tryGenerateSessionJsonUnionType(propSchema, parentClassName, propName, knownTypes, nestedClasses, enumOutput); if (unionType) return isRequired ? unionType : `${unionType}?`; - return !isRequired ? "object?" : "object"; + return !isRequired ? "JsonElement?" : "JsonElement"; } if (propSchema.oneOf) { const unionType = tryGenerateSessionJsonUnionType(propSchema, parentClassName, propName, knownTypes, nestedClasses, enumOutput); if (unionType) return isRequired ? unionType : `${unionType}?`; - return !isRequired ? "object?" : "object"; + return !isRequired ? "JsonElement?" : "JsonElement"; } if (propSchema.enum && Array.isArray(propSchema.enum)) { const enumName = getOrCreateEnum(parentClassName, propName, propSchema.enum as string[], enumOutput, propSchema.description, getEnumValueDescriptions(propSchema), propSchema.title as string | undefined, isSchemaDeprecated(propSchema), isSchemaExperimental(propSchema)); @@ -1610,7 +1611,6 @@ function emitRpcClass( let propAccessors = "{ get; set; }"; if (isReq && !csharpType.endsWith("?")) { if (csharpType === "string") defaultVal = " = string.Empty;"; - else if (csharpType === "object") defaultVal = " = null!;"; else if (csharpType.startsWith("IList<")) { propAccessors = "{ get => field ??= []; set; }"; } else if (csharpType.startsWith("IDictionary<")) { From 78c1500c6c819ace26a9bbee384be84e9831007d Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 13:52:33 +0100 Subject: [PATCH 02/40] Phase 3: seal hand-written public types Seal all hand-written leaf classes in Types.cs (70 classes). Kept non-sealed: - McpServerConfig: existing polymorphic abstract base - SessionConfig / ResumeSessionConfig: will be refactored to share a base in Phase 5 - SessionLifecycleEvent: will become polymorphic base in Phase 4 - CopilotClientOptions / MessageOptions: existing protected Clone(...) ctor + virtual Clone() pattern - SessionFsProvider: existing abstract base intended for consumer subclassing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Client.cs | 2 +- dotnet/src/SessionFsProvider.cs | 2 +- dotnet/src/Types.cs | 208 ++++++++++++++++---------------- 3 files changed, 106 insertions(+), 106 deletions(-) diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index a42dbbbb6..ea865371a 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -2209,7 +2209,7 @@ internal partial class ClientJsonContext : JsonSerializerContext; /// back through Microsoft.Extensions.AI without JSON serialization. /// /// The tool result to wrap. -public class ToolResultAIContent(ToolResultObject toolResult) : AIContent +public sealed class ToolResultAIContent(ToolResultObject toolResult) : AIContent { /// /// Gets the underlying . diff --git a/dotnet/src/SessionFsProvider.cs b/dotnet/src/SessionFsProvider.cs index ef7845a31..a48033f07 100644 --- a/dotnet/src/SessionFsProvider.cs +++ b/dotnet/src/SessionFsProvider.cs @@ -12,7 +12,7 @@ namespace GitHub.Copilot.SDK; /// Same shape as but without the Error field, /// since providers signal errors by throwing. /// -public class SessionFsSqliteResult +public sealed class SessionFsSqliteResult { /// Column names from the result set. public IList Columns { get; set; } = []; diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 0cf559a8c..4ac583060 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -335,7 +335,7 @@ public sealed class SessionFsConfig /// /// Represents a binary result returned by a tool invocation. /// -public class ToolBinaryResult +public sealed class ToolBinaryResult { /// /// Base64-encoded binary data. @@ -365,7 +365,7 @@ public class ToolBinaryResult /// /// Represents the structured result of a tool execution. /// -public class ToolResultObject +public sealed class ToolResultObject { /// /// Text result to be consumed by the language model. @@ -382,10 +382,10 @@ public class ToolResultObject /// /// Result type indicator. /// - /// "success" — the tool executed successfully. - /// "failure" — the tool encountered an error. - /// "rejected" — the tool invocation was rejected. - /// "denied" — the tool invocation was denied by a permission check. + /// "success" — the tool executed successfully. + /// "failure" — the tool encountered an error. + /// "rejected" — the tool invocation was rejected. + /// "denied" — the tool invocation was denied by a permission check. /// /// [JsonPropertyName("resultType")] @@ -502,7 +502,7 @@ private static string SerializeAIContent(AIContent content) => /// /// Contains context for a tool invocation callback. /// -public class ToolInvocation +public sealed class ToolInvocation { /// /// Identifier of the session that triggered the tool call. @@ -617,16 +617,16 @@ public override void Write(Utf8JsonWriter writer, PermissionRequestResultKind va /// /// Result of a permission request evaluation. /// -public class PermissionRequestResult +public sealed class PermissionRequestResult { /// /// Permission decision kind. Use the static members of /// to construct values. Valid kinds are: /// - /// "approve-once" () — allow this single request. - /// "reject" () — deny the request. - /// "user-not-available" () — deny because no user is available to confirm. - /// "no-result" () — leave the pending request unanswered (protocol v1 only; rejected by protocol v2 servers). + /// "approve-once" () — allow this single request. + /// "reject" () — deny the request. + /// "user-not-available" () — deny because no user is available to confirm. + /// "no-result" () — leave the pending request unanswered (protocol v1 only; rejected by protocol v2 servers). /// /// [JsonPropertyName("kind")] @@ -642,7 +642,7 @@ public class PermissionRequestResult /// /// Contains context for a permission request callback. /// -public class PermissionInvocation +public sealed class PermissionInvocation { /// /// Identifier of the session that triggered the permission request. @@ -662,7 +662,7 @@ public class PermissionInvocation /// /// Request for user input from the agent. /// -public class UserInputRequest +public sealed class UserInputRequest { /// /// The question to ask the user. @@ -686,7 +686,7 @@ public class UserInputRequest /// /// Response to a user input request. /// -public class UserInputResponse +public sealed class UserInputResponse { /// /// The user's answer. @@ -704,7 +704,7 @@ public class UserInputResponse /// /// Context for a user input request invocation. /// -public class UserInputInvocation +public sealed class UserInputInvocation { /// /// Identifier of the session that triggered the user input request. @@ -720,7 +720,7 @@ public class UserInputInvocation /// /// Request to exit plan mode and continue with a selected action. /// -public class ExitPlanModeRequest +public sealed class ExitPlanModeRequest { /// /// Summary of the plan or proposed next step. @@ -750,7 +750,7 @@ public class ExitPlanModeRequest /// /// Response to an exit-plan-mode request. /// -public class ExitPlanModeResult +public sealed class ExitPlanModeResult { /// /// Whether the user approved exiting plan mode. @@ -774,7 +774,7 @@ public class ExitPlanModeResult /// /// Context for an exit-plan-mode request invocation. /// -public class ExitPlanModeInvocation +public sealed class ExitPlanModeInvocation { /// /// Identifier of the session that triggered the request. @@ -790,7 +790,7 @@ public class ExitPlanModeInvocation /// /// Request to switch to auto mode after an eligible rate limit. /// -public class AutoModeSwitchRequest +public sealed class AutoModeSwitchRequest { /// /// The rate-limit error code that triggered the request. @@ -808,7 +808,7 @@ public class AutoModeSwitchRequest /// /// Context for an auto-mode-switch request invocation. /// -public class AutoModeSwitchInvocation +public sealed class AutoModeSwitchInvocation { /// /// Identifier of the session that triggered the request. @@ -828,7 +828,7 @@ public class AutoModeSwitchInvocation /// /// Defines a slash-command that users can invoke from the CLI TUI. /// -public class CommandDefinition +public sealed class CommandDefinition { /// /// Command name (without leading /). For example, "deploy". @@ -849,7 +849,7 @@ public class CommandDefinition /// /// Context passed to a when a command is executed. /// -public class CommandContext +public sealed class CommandContext { /// /// Session ID where the command was invoked. @@ -878,13 +878,13 @@ public class CommandContext public delegate Task CommandHandler(CommandContext context); // ============================================================================ -// Elicitation Types (UI — client → server) +// Elicitation Types (UI — client → server) // ============================================================================ /// /// JSON Schema describing the form fields to present for an elicitation dialog. /// -public class ElicitationSchema +public sealed class ElicitationSchema { /// /// Schema type indicator (always "object"). @@ -908,7 +908,7 @@ public class ElicitationSchema /// /// Parameters for an elicitation request sent from the SDK to the server. /// -public class ElicitationParams +public sealed class ElicitationParams { /// /// Message describing what information is needed from the user. @@ -924,7 +924,7 @@ public class ElicitationParams /// /// Result returned from an elicitation dialog. /// -public class ElicitationResult +public sealed class ElicitationResult { /// /// User action: "accept" (submitted), "decline" (rejected), or "cancel" (dismissed). @@ -940,7 +940,7 @@ public class ElicitationResult /// /// Options for the convenience method. /// -public class InputOptions +public sealed class InputOptions { /// Title label for the input field. public string? Title { get; set; } @@ -1009,14 +1009,14 @@ public interface ISessionUiApi } // ============================================================================ -// Elicitation Types (server → client callback) +// Elicitation Types (server → client callback) // ============================================================================ /// /// Context for an elicitation handler invocation, combining the request data /// with session context. Mirrors the single-argument pattern of . /// -public class ElicitationContext +public sealed class ElicitationContext { /// Identifier of the session that triggered the elicitation request. public string SessionId { get; set; } = string.Empty; @@ -1049,7 +1049,7 @@ public class ElicitationContext /// /// Represents the capabilities reported by the host for a session. /// -public class SessionCapabilities +public sealed class SessionCapabilities { /// /// UI-related capabilities. @@ -1060,7 +1060,7 @@ public class SessionCapabilities /// /// UI-specific capability flags for a session. /// -public class SessionUiCapabilities +public sealed class SessionUiCapabilities { /// /// Whether the host supports interactive elicitation dialogs. @@ -1075,7 +1075,7 @@ public class SessionUiCapabilities /// /// Context for a hook invocation. /// -public class HookInvocation +public sealed class HookInvocation { /// /// Identifier of the session that triggered the hook. @@ -1086,7 +1086,7 @@ public class HookInvocation /// /// Input for a pre-tool-use hook. /// -public class PreToolUseHookInput +public sealed class PreToolUseHookInput { /// /// The runtime session ID of the session that triggered the hook. @@ -1122,14 +1122,14 @@ public class PreToolUseHookInput /// /// Output for a pre-tool-use hook. /// -public class PreToolUseHookOutput +public sealed class PreToolUseHookOutput { /// /// Permission decision for the pending tool call. /// - /// "allow" — permit the tool to execute. - /// "deny" — block the tool from executing. - /// "ask" — fall through to the normal permission prompt. + /// "allow" — permit the tool to execute. + /// "deny" — block the tool from executing. + /// "ask" — fall through to the normal permission prompt. /// /// [JsonPropertyName("permissionDecision")] @@ -1168,7 +1168,7 @@ public class PreToolUseHookOutput /// /// Input for a post-tool-use hook. /// -public class PostToolUseHookInput +public sealed class PostToolUseHookInput { /// /// The runtime session ID of the session that triggered the hook. @@ -1210,7 +1210,7 @@ public class PostToolUseHookInput /// /// Output for a post-tool-use hook. /// -public class PostToolUseHookOutput +public sealed class PostToolUseHookOutput { /// /// Modified result to replace the original tool result. @@ -1239,7 +1239,7 @@ public class PostToolUseHookOutput /// /// Input for a user-prompt-submitted hook. /// -public class UserPromptSubmittedHookInput +public sealed class UserPromptSubmittedHookInput { /// /// The runtime session ID of the session that triggered the hook. @@ -1269,7 +1269,7 @@ public class UserPromptSubmittedHookInput /// /// Output for a user-prompt-submitted hook. /// -public class UserPromptSubmittedHookOutput +public sealed class UserPromptSubmittedHookOutput { /// /// Modified prompt to use instead of the original user prompt. @@ -1298,7 +1298,7 @@ public class UserPromptSubmittedHookOutput /// /// Input for a session-start hook. /// -public class SessionStartHookInput +public sealed class SessionStartHookInput { /// /// The runtime session ID of the session that triggered the hook. @@ -1321,9 +1321,9 @@ public class SessionStartHookInput /// /// Source of the session start. /// - /// "startup" — initial application startup. - /// "resume" — resuming a previous session. - /// "new" — starting a brand new session. + /// "startup" — initial application startup. + /// "resume" — resuming a previous session. + /// "new" — starting a brand new session. /// /// [JsonPropertyName("source")] @@ -1339,7 +1339,7 @@ public class SessionStartHookInput /// /// Output for a session-start hook. /// -public class SessionStartHookOutput +public sealed class SessionStartHookOutput { /// /// Additional context to inject into the session for the language model. @@ -1362,7 +1362,7 @@ public class SessionStartHookOutput /// /// Input for a session-end hook. /// -public class SessionEndHookInput +public sealed class SessionEndHookInput { /// /// The runtime session ID of the session that triggered the hook. @@ -1385,11 +1385,11 @@ public class SessionEndHookInput /// /// Reason for session end. /// - /// "complete" — the session finished normally. - /// "error" — the session ended due to an error. - /// "abort" — the session was aborted. - /// "timeout" — the session timed out. - /// "user_exit" — the user exited the session. + /// "complete" — the session finished normally. + /// "error" — the session ended due to an error. + /// "abort" — the session was aborted. + /// "timeout" — the session timed out. + /// "user_exit" — the user exited the session. /// /// [JsonPropertyName("reason")] @@ -1411,7 +1411,7 @@ public class SessionEndHookInput /// /// Output for a session-end hook. /// -public class SessionEndHookOutput +public sealed class SessionEndHookOutput { /// /// Whether to suppress the session end output from the conversation. @@ -1440,7 +1440,7 @@ public class SessionEndHookOutput /// /// Input for an error-occurred hook. /// -public class ErrorOccurredHookInput +public sealed class ErrorOccurredHookInput { /// /// The runtime session ID of the session that triggered the hook. @@ -1469,10 +1469,10 @@ public class ErrorOccurredHookInput /// /// Context of the error. /// - /// "model_call" — error during a model API call. - /// "tool_execution" — error during tool execution. - /// "system" — internal system error. - /// "user_input" — error processing user input. + /// "model_call" — error during a model API call. + /// "tool_execution" — error during tool execution. + /// "system" — internal system error. + /// "user_input" — error processing user input. /// /// [JsonPropertyName("errorContext")] @@ -1488,7 +1488,7 @@ public class ErrorOccurredHookInput /// /// Output for an error-occurred hook. /// -public class ErrorOccurredHookOutput +public sealed class ErrorOccurredHookOutput { /// /// Whether to suppress the error output from the conversation. @@ -1499,9 +1499,9 @@ public class ErrorOccurredHookOutput /// /// Error handling strategy. /// - /// "retry" — retry the failed operation. - /// "skip" — skip the failed operation and continue. - /// "abort" — abort the session. + /// "retry" — retry the failed operation. + /// "skip" — skip the failed operation and continue. + /// "abort" — abort the session. /// /// [JsonPropertyName("errorHandling")] @@ -1528,7 +1528,7 @@ public class ErrorOccurredHookOutput /// /// Hook handlers configuration for a session. /// -public class SessionHooks +public sealed class SessionHooks { /// /// Handler called before a tool is executed. @@ -1604,7 +1604,7 @@ public enum SectionOverrideAction /// /// Override operation for a single system prompt section. /// -public class SectionOverride +public sealed class SectionOverride { /// /// The operation to perform on this section. Ignored when Transform is set. @@ -1621,7 +1621,7 @@ public class SectionOverride /// /// Transform callback. When set, takes precedence over Action. /// Receives current section content, returns transformed content. - /// Not serialized — the SDK handles this locally. + /// Not serialized — the SDK handles this locally. /// [JsonIgnore] public Func>? Transform { get; set; } @@ -1657,7 +1657,7 @@ public static class SystemPromptSections /// /// Configuration for the system message used in a session. /// -public class SystemMessageConfig +public sealed class SystemMessageConfig { /// /// How the system message is applied (append, replace, or customize). @@ -1680,7 +1680,7 @@ public class SystemMessageConfig /// /// Configuration for a custom model provider. /// -public class ProviderConfig +public sealed class ProviderConfig { /// /// Provider type identifier (e.g., "openai", "azure"). @@ -1764,7 +1764,7 @@ public class ProviderConfig /// /// Azure OpenAI-specific provider options. /// -public class AzureOptions +public sealed class AzureOptions { /// /// Azure OpenAI API version to use (e.g., "2024-02-01"). @@ -1904,7 +1904,7 @@ public sealed class McpHttpServerConfig : McpServerConfig /// /// Configuration for a custom agent. /// -public class CustomAgentConfig +public sealed class CustomAgentConfig { /// /// Unique name of the custom agent. @@ -1972,7 +1972,7 @@ public class CustomAgentConfig /// Use to hide specific tools from the default agent /// while keeping them available to custom sub-agents. /// -public class DefaultAgentConfig +public sealed class DefaultAgentConfig { /// /// List of tool names to exclude from the default agent. @@ -1987,7 +1987,7 @@ public class DefaultAgentConfig /// When enabled, sessions automatically manage context window limits through background compaction /// and persist state to a workspace directory. /// -public class InfiniteSessionConfig +public sealed class InfiniteSessionConfig { /// /// Whether infinite sessions are enabled. Default: true @@ -2015,7 +2015,7 @@ public class InfiniteSessionConfig /// /// GitHub repository metadata to associate with a cloud session. /// -public class CloudSessionRepository +public sealed class CloudSessionRepository { /// Repository owner. public required string Owner { get; set; } @@ -2030,7 +2030,7 @@ public class CloudSessionRepository /// /// Options for creating a remote session in the cloud. /// -public class CloudSessionOptions +public sealed class CloudSessionOptions { /// /// Optional GitHub repository metadata to associate with the cloud session. @@ -2318,9 +2318,9 @@ protected SessionConfig(SessionConfig? other) /// /// Per-session remote behavior control: /// - /// "off" — local only, no remote export (default) - /// "export" — export session events to GitHub without enabling remote steering - /// "on" — export to GitHub AND enable remote steering + /// "off" — local only, no remote export (default) + /// "export" — export session events to GitHub without enabling remote steering + /// "on" — export to GitHub AND enable remote steering /// /// public RemoteSessionMode? RemoteSession { get; set; } @@ -2724,7 +2724,7 @@ public virtual MessageOptions Clone() /// /// Working directory context for a session. /// -public class SessionContext +public sealed class SessionContext { /// Working directory where the session was created. public string Cwd { get; set; } = string.Empty; @@ -2739,7 +2739,7 @@ public class SessionContext /// /// Filter options for listing sessions. /// -public class SessionListFilter +public sealed class SessionListFilter { /// Filter by exact cwd match. public string? Cwd { get; set; } @@ -2754,7 +2754,7 @@ public class SessionListFilter /// /// Metadata describing a Copilot session. /// -public class SessionMetadata +public sealed class SessionMetadata { /// /// Unique identifier of the session. @@ -2788,7 +2788,7 @@ internal class PingRequest /// /// Response from a server ping request. /// -public class PingResponse +public sealed class PingResponse { /// /// Echo of the ping message. @@ -2807,7 +2807,7 @@ public class PingResponse /// /// Response from status.get /// -public class GetStatusResponse +public sealed class GetStatusResponse { /// Package version (e.g., "1.0.0") [JsonPropertyName("version")] @@ -2821,7 +2821,7 @@ public class GetStatusResponse /// /// Response from auth.getStatus /// -public class GetAuthStatusResponse +public sealed class GetAuthStatusResponse { /// Whether the user is authenticated [JsonPropertyName("isAuthenticated")] @@ -2830,12 +2830,12 @@ public class GetAuthStatusResponse /// /// Authentication type. /// - /// "user" — authenticated via user login. - /// "env" — authenticated via environment variable. - /// "gh-cli" — authenticated via the GitHub CLI. - /// "hmac" — authenticated via HMAC signature. - /// "api-key" — authenticated via API key. - /// "token" — authenticated via explicit token. + /// "user" — authenticated via user login. + /// "env" — authenticated via environment variable. + /// "gh-cli" — authenticated via the GitHub CLI. + /// "hmac" — authenticated via HMAC signature. + /// "api-key" — authenticated via API key. + /// "token" — authenticated via explicit token. /// /// [JsonPropertyName("authType")] @@ -2857,7 +2857,7 @@ public class GetAuthStatusResponse /// /// Model vision-specific limits /// -public class ModelVisionLimits +public sealed class ModelVisionLimits { /// /// List of supported image MIME types (e.g., "image/png", "image/jpeg"). @@ -2881,7 +2881,7 @@ public class ModelVisionLimits /// /// Model limits /// -public class ModelLimits +public sealed class ModelLimits { /// /// Maximum number of tokens allowed in the prompt. @@ -2905,7 +2905,7 @@ public class ModelLimits /// /// Model support flags /// -public class ModelSupports +public sealed class ModelSupports { /// /// Whether this model supports image/vision inputs. @@ -2923,7 +2923,7 @@ public class ModelSupports /// /// Model capabilities and limits /// -public class ModelCapabilities +public sealed class ModelCapabilities { /// /// Feature support flags for the model. @@ -2941,7 +2941,7 @@ public class ModelCapabilities /// /// Model policy state /// -public class ModelPolicy +public sealed class ModelPolicy { /// /// Policy state of the model (e.g., "enabled", "disabled"). @@ -2959,7 +2959,7 @@ public class ModelPolicy /// /// Model billing information /// -public class ModelBilling +public sealed class ModelBilling { /// /// Billing cost multiplier relative to the base model rate. @@ -2971,7 +2971,7 @@ public class ModelBilling /// /// Information about an available model /// -public class ModelInfo +public sealed class ModelInfo { /// Model identifier (e.g., "claude-sonnet-4.5") [JsonPropertyName("id")] @@ -3005,7 +3005,7 @@ public class ModelInfo /// /// Response from models.list /// -public class GetModelsResponse +public sealed class GetModelsResponse { /// /// List of available models. @@ -3038,7 +3038,7 @@ public static class SessionLifecycleEventTypes /// /// Metadata for session lifecycle events /// -public class SessionLifecycleEventMetadata +public sealed class SessionLifecycleEventMetadata { /// /// ISO 8601 timestamp when the session was created. @@ -3086,7 +3086,7 @@ public class SessionLifecycleEvent /// /// Response from session.getForeground /// -public class GetForegroundSessionResponse +public sealed class GetForegroundSessionResponse { /// /// Identifier of the current foreground session, or null if none. @@ -3104,7 +3104,7 @@ public class GetForegroundSessionResponse /// /// Response from session.setForeground /// -public class SetForegroundSessionResponse +public sealed class SetForegroundSessionResponse { /// /// Whether the foreground session was set successfully. @@ -3122,7 +3122,7 @@ public class SetForegroundSessionResponse /// /// Content data for a single system prompt section in a transform RPC call. /// -public class SystemMessageTransformSection +public sealed class SystemMessageTransformSection { /// /// The content of the section. @@ -3134,7 +3134,7 @@ public class SystemMessageTransformSection /// /// Response to a systemMessage.transform RPC call. /// -public class SystemMessageTransformRpcResponse +public sealed class SystemMessageTransformRpcResponse { /// /// The transformed sections keyed by section identifier. @@ -3189,4 +3189,4 @@ public class SystemMessageTransformRpcResponse [JsonSerializable(typeof(object))] [JsonSerializable(typeof(Dictionary))] [JsonSerializable(typeof(string[]))] -internal partial class TypesJsonContext : JsonSerializerContext; +internal partial class TypesJsonContext : JsonSerializerContext; \ No newline at end of file From 2c9a74a42957f5375a4022be8e86fcb8765d6250 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 13:55:07 +0100 Subject: [PATCH 03/40] Phase 4a: simple property/method renames - CopilotSession.GetMessagesAsync -> GetEventsAsync - (Resume)SessionConfig.OnExitPlanMode -> OnExitPlanModeRequest - (Resume)SessionConfig.OnAutoModeSwitch -> OnAutoModeSwitchRequest - (Resume)SessionConfig.CreateSessionFsHandler -> CreateSessionFsProvider - ResumeSessionConfig.DisableResume -> SuppressResumeEvent - ProviderConfig.MaxInputTokens -> MaxPromptTokens - InputOptions -> UiInputOptions - ISessionUiApi.ElicitationAsync -> ElicitAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 64 +++++++++---------- dotnet/src/Client.cs | 32 +++++----- dotnet/src/Session.cs | 34 +++++----- dotnet/src/Types.cs | 38 +++++------ dotnet/test/E2E/ElicitationE2ETests.cs | 14 ++-- dotnet/test/E2E/ErrorResilienceE2ETests.cs | 4 +- dotnet/test/E2E/EventFidelityE2ETests.cs | 6 +- dotnet/test/E2E/ModeHandlersE2ETests.cs | 6 +- .../MultiClientCommandsElicitationE2ETests.cs | 12 ++-- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 4 +- .../test/E2E/RpcEventSideEffectsE2ETests.cs | 10 +-- dotnet/test/E2E/RpcSessionStateE2ETests.cs | 16 ++--- dotnet/test/E2E/RpcShellAndFleetE2ETests.cs | 4 +- dotnet/test/E2E/SessionConfigE2ETests.cs | 18 +++--- dotnet/test/E2E/SessionE2ETests.cs | 24 +++---- dotnet/test/E2E/SessionFsE2ETests.cs | 20 +++--- dotnet/test/E2E/SessionFsSqliteE2ETests.cs | 6 +- dotnet/test/E2E/SessionLifecycleE2ETests.cs | 4 +- dotnet/test/E2E/StreamingFidelityE2ETests.cs | 6 +- dotnet/test/Harness/TestHelper.cs | 6 +- dotnet/test/Unit/CloneTests.cs | 18 +++--- dotnet/test/Unit/SerializationTests.cs | 6 +- 22 files changed, 176 insertions(+), 176 deletions(-) diff --git a/dotnet/README.md b/dotnet/README.md index 012c51c17..1aa444d97 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -1,4 +1,4 @@ -# Copilot SDK +# Copilot SDK SDK for programmatic control of GitHub Copilot CLI. @@ -85,7 +85,7 @@ new CopilotClient(CopilotClientOptions? options = null) - `Logger` - `ILogger` instance for SDK logging - `GitHubToken` - GitHub token for authentication. When provided, takes priority over other auth methods. - `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `CliUrl`. -- `Telemetry` - OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. +- `Telemetry` - OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. #### Methods @@ -226,13 +226,13 @@ subscription.Dispose(); Abort the currently processing message in this session. -##### `GetMessagesAsync(): Task>` +##### `GetEventsAsync(): Task>` Get all events/messages from this session. ##### `DisposeAsync(): ValueTask` -Close the session and release in-memory resources. Session data on disk is preserved — the conversation can be resumed later via `ResumeSessionAsync()`. To permanently delete session data, use `client.DeleteSessionAsync()`. +Close the session and release in-memory resources. Session data on disk is preserved — the conversation can be resumed later via `ResumeSessionAsync()`. To permanently delete session data, use `client.DeleteSessionAsync()`. ```csharp // Preferred: automatic cleanup via await using @@ -281,7 +281,7 @@ session.On(evt => The SDK supports image attachments via the `Attachments` parameter. You can attach images by providing their file path, or by passing base64-encoded data directly using a blob attachment: ```csharp -// File attachment — runtime reads from disk +// File attachment — runtime reads from disk await session.SendAsync(new MessageOptions { Prompt = "What's in this image?", @@ -295,7 +295,7 @@ await session.SendAsync(new MessageOptions } }); -// Blob attachment — provide base64 data directly +// Blob attachment — provide base64 data directly await session.SendAsync(new MessageOptions { Prompt = "What's in this image?", @@ -524,7 +524,7 @@ var session = await client.CreateSessionAsync(new SessionConfig Handler = async (context) => { Console.WriteLine($"Deploying with args: {context.Args}"); - // Do work here — any thrown error is reported back to the CLI + // Do work here — any thrown error is reported back to the CLI }, }, ], @@ -537,9 +537,9 @@ Commands are sent to the CLI on both `CreateSessionAsync` and `ResumeSessionAsyn ## UI Elicitation -When the session has elicitation support — either from the CLI's TUI or from another client that registered an `OnElicitationRequest` handler (see [Elicitation Requests](#elicitation-requests)) — the SDK can request interactive form dialogs from the user. The `session.Ui` object provides convenience methods built on a single generic elicitation RPC. +When the session has elicitation support — either from the CLI's TUI or from another client that registered an `OnElicitationRequest` handler (see [Elicitation Requests](#elicitation-requests)) — the SDK can request interactive form dialogs from the user. The `session.Ui` object provides convenience methods built on a single generic elicitation RPC. -> **Capability check:** Elicitation is only available when at least one connected participant advertises support. Always check `session.Capabilities.Ui?.Elicitation` before calling UI methods — this property updates automatically as participants join and leave. +> **Capability check:** Elicitation is only available when at least one connected participant advertises support. Always check `session.Capabilities.Ui?.Elicitation` before calling UI methods — this property updates automatically as participants join and leave. ```csharp var session = await client.CreateSessionAsync(new SessionConfig @@ -550,15 +550,15 @@ var session = await client.CreateSessionAsync(new SessionConfig if (session.Capabilities.Ui?.Elicitation == true) { - // Confirm dialog — returns boolean + // Confirm dialog — returns boolean bool ok = await session.Ui.ConfirmAsync("Deploy to production?"); - // Selection dialog — returns selected value or null + // Selection dialog — returns selected value or null string? env = await session.Ui.SelectAsync("Pick environment", ["production", "staging", "dev"]); - // Text input — returns string or null - string? name = await session.Ui.InputAsync("Project name:", new InputOptions + // Text input — returns string or null + string? name = await session.Ui.InputAsync("Project name:", new UiInputOptions { Title = "Name", MinLength = 1, @@ -566,7 +566,7 @@ if (session.Capabilities.Ui?.Elicitation == true) }); // Generic elicitation with full schema control - ElicitationResult result = await session.Ui.ElicitationAsync(new ElicitationParams + ElicitationResult result = await session.Ui.ElicitAsync(new ElicitationParams { Message = "Configure deployment", RequestedSchema = new ElicitationSchema @@ -727,7 +727,7 @@ var client = new CopilotClient(new CopilotClientOptions Trace context (`traceparent`/`tracestate`) is automatically propagated between the SDK and CLI on `CreateSessionAsync`, `ResumeSessionAsync`, and `SendAsync` calls, and inbound when the CLI invokes tool handlers. -No extra dependencies — uses built-in `System.Diagnostics.Activity`. +No extra dependencies — uses built-in `System.Diagnostics.Activity`. ## Permission Handling @@ -757,19 +757,19 @@ var session = await client.CreateSessionAsync(new SessionConfig Model = "gpt-5", OnPermissionRequest = async (request, invocation) => { - // request.Kind — string discriminator for the type of operation being requested: - // "shell" — executing a shell command - // "write" — writing or editing a file - // "read" — reading a file - // "mcp" — calling an MCP tool - // "custom_tool" — calling one of your registered tools - // "url" — fetching a URL - // "memory" — accessing or modifying assistant memory - // "hook" — invoking a registered hook - // request.ToolCallId — the tool call that triggered this request - // request.ToolName — name of the tool (for custom-tool / mcp) - // request.FileName — file being written (for write) - // request.FullCommandText — full shell command text (for shell) + // request.Kind — string discriminator for the type of operation being requested: + // "shell" — executing a shell command + // "write" — writing or editing a file + // "read" — reading a file + // "mcp" — calling an MCP tool + // "custom_tool" — calling one of your registered tools + // "url" — fetching a URL + // "memory" — accessing or modifying assistant memory + // "hook" — invoking a registered hook + // request.ToolCallId — the tool call that triggered this request + // request.ToolName — name of the tool (for custom-tool / mcp) + // request.FileName — file being written (for write) + // request.FullCommandText — full shell command text (for shell) if (request.Kind == "shell") { @@ -784,7 +784,7 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Permission Result Kinds -The `Kind` property must be one of the canonical `PermissionRequestResultKind` values. Approval decisions are present-tense — they describe the decision to apply, not the past-tense outcome reported back on `permission.completed` session events. +The `Kind` property must be one of the canonical `PermissionRequestResultKind` values. Approval decisions are present-tense — they describe the decision to apply, not the past-tense outcome reported back on `permission.completed` session events. | Value | Wire value | Meaning | | ------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | @@ -793,7 +793,7 @@ The `Kind` property must be one of the canonical `PermissionRequestResultKind` v | `PermissionRequestResultKind.UserNotAvailable` | `"user-not-available"` | Deny the request because no user is available to confirm it | | `PermissionRequestResultKind.NoResult` | `"no-result"` | Leave the permission request unanswered (the SDK returns without calling the RPC). Not allowed for protocol v2 permission requests (will be rejected). | -> The past-tense names `PermissionRequestResultKind.DeniedInteractivelyByUser`, `PermissionRequestResultKind.DeniedCouldNotRequestFromUser`, and `PermissionRequestResultKind.DeniedByRules` remain as `[Obsolete]` aliases for backward compatibility — prefer the canonical members above in new code. +> The past-tense names `PermissionRequestResultKind.DeniedInteractivelyByUser`, `PermissionRequestResultKind.DeniedCouldNotRequestFromUser`, and `PermissionRequestResultKind.DeniedByRules` remain as `[Obsolete]` aliases for backward compatibility — prefer the canonical members above in new code. ### Resuming Sessions @@ -924,7 +924,7 @@ var session = await client.CreateSessionAsync(new SessionConfig ## Elicitation Requests -Register an `OnElicitationRequest` handler to let your client act as an elicitation provider — presenting form-based UI dialogs on behalf of the agent. When provided, the server notifies your client whenever a tool or MCP server needs structured user input. +Register an `OnElicitationRequest` handler to let your client act as an elicitation provider — presenting form-based UI dialogs on behalf of the agent. When provided, the server notifies your client whenever a tool or MCP server needs structured user input. ```csharp var session = await client.CreateSessionAsync(new SessionConfig @@ -964,7 +964,7 @@ In multi-client scenarios: - If no connected client was previously providing an elicitation capability, but a new client joins that can, all clients will receive a `capabilities.changed` event to notify them that elicitation is now possible. The SDK automatically updates `session.Capabilities` when these events arrive. - Similarly, if the last elicitation provider disconnects, all clients receive a `capabilities.changed` event indicating elicitation is no longer available. -- The server fans out elicitation requests to **all** connected clients that registered a handler — the first response wins. +- The server fans out elicitation requests to **all** connected clients that registered a handler — the first response wins. ## Error Handling diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index ea865371a..efcbc0eef 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -570,8 +570,8 @@ public async Task CreateSessionAsync(SessionConfig config, Cance session.RegisterPermissionHandler(config.OnPermissionRequest); session.RegisterCommands(config.Commands); session.RegisterElicitationHandler(config.OnElicitationRequest); - session.RegisterExitPlanModeHandler(config.OnExitPlanMode); - session.RegisterAutoModeSwitchHandler(config.OnAutoModeSwitch); + session.RegisterExitPlanModeHandler(config.OnExitPlanModeRequest); + session.RegisterAutoModeSwitchHandler(config.OnAutoModeSwitchRequest); if (config.OnUserInputRequest != null) { session.RegisterUserInputHandler(config.OnUserInputRequest); @@ -588,7 +588,7 @@ public async Task CreateSessionAsync(SessionConfig config, Cance { session.On(config.OnEvent); } - ConfigureSessionFsHandlers(session, config.CreateSessionFsHandler); + ConfigureSessionFsHandlers(session, config.CreateSessionFsProvider); RegisterSession(session); session.StartProcessingEvents(); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, @@ -616,8 +616,8 @@ public async Task CreateSessionAsync(SessionConfig config, Cance config.EnableSessionTelemetry, (bool?)true, config.OnUserInputRequest != null ? true : null, - config.OnExitPlanMode != null ? true : null, - config.OnAutoModeSwitch != null ? true : null, + config.OnExitPlanModeRequest != null ? true : null, + config.OnAutoModeSwitchRequest != null ? true : null, hasHooks ? true : null, config.WorkingDirectory, config.Streaming is true ? true : null, @@ -728,8 +728,8 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes session.RegisterPermissionHandler(config.OnPermissionRequest); session.RegisterCommands(config.Commands); session.RegisterElicitationHandler(config.OnElicitationRequest); - session.RegisterExitPlanModeHandler(config.OnExitPlanMode); - session.RegisterAutoModeSwitchHandler(config.OnAutoModeSwitch); + session.RegisterExitPlanModeHandler(config.OnExitPlanModeRequest); + session.RegisterAutoModeSwitchHandler(config.OnAutoModeSwitchRequest); if (config.OnUserInputRequest != null) { session.RegisterUserInputHandler(config.OnUserInputRequest); @@ -746,7 +746,7 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes { session.On(config.OnEvent); } - ConfigureSessionFsHandlers(session, config.CreateSessionFsHandler); + ConfigureSessionFsHandlers(session, config.CreateSessionFsProvider); RegisterSession(session); session.StartProcessingEvents(); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, @@ -774,13 +774,13 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes config.EnableSessionTelemetry, (bool?)true, config.OnUserInputRequest != null ? true : null, - config.OnExitPlanMode != null ? true : null, - config.OnAutoModeSwitch != null ? true : null, + config.OnExitPlanModeRequest != null ? true : null, + config.OnAutoModeSwitchRequest != null ? true : null, hasHooks ? true : null, config.WorkingDirectory, config.ConfigDir, config.EnableConfigDiscovery, - config.DisableResume is true ? true : null, + config.SuppressResumeEvent is true ? true : null, config.Streaming is true ? true : null, config.IncludeSubAgentStreamingEvents, config.McpServers, @@ -1343,11 +1343,11 @@ private void ConfigureSessionFsHandlers(CopilotSession session, Func( connection.Rpc, "ping", [new PingRequest()], connection.StderrBuffer, cancellationToken); @@ -2078,7 +2078,7 @@ internal record ResumeSessionRequest( string? WorkingDirectory, string? ConfigDir, bool? EnableConfigDiscovery, - bool? DisableResume, + bool? SuppressResumeEvent, bool? Streaming, bool? IncludeSubAgentStreamingEvents, IDictionary? McpServers, diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index ffbd2fa21..836d5a174 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -31,7 +31,7 @@ namespace GitHub.Copilot.SDK; /// implements . Use the /// await using pattern for automatic cleanup, or call /// explicitly. Disposing a session releases in-memory resources but preserves session data -/// on disk — the conversation can be resumed later via +/// on disk — the conversation can be resumed later via /// . To permanently delete session data, /// use . /// @@ -421,7 +421,7 @@ internal void DispatchEvent(SessionEvent sessionEvent) { // Fire broadcast work concurrently (fire-and-forget with error logging). // This is done outside the channel so broadcast handlers don't block the - // consumer loop — important when a secondary client's handler intentionally + // consumer loop — important when a secondary client's handler intentionally // never completes (multi-client permission scenario). _ = HandleBroadcastEventAsync(sessionEvent); @@ -710,11 +710,11 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, } catch (IOException) { - // Connection lost or RPC error — nothing we can do + // Connection lost or RPC error — nothing we can do } catch (ObjectDisposedException) { - // Connection already disposed — nothing we can do + // Connection already disposed — nothing we can do } } } @@ -761,11 +761,11 @@ private async Task ExecutePermissionAndRespondAsync(string requestId, Permission } catch (IOException) { - // Connection lost or RPC error — nothing we can do + // Connection lost or RPC error — nothing we can do } catch (ObjectDisposedException) { - // Connection already disposed — nothing we can do + // Connection already disposed — nothing we can do } } } @@ -843,7 +843,7 @@ private async Task ExecuteCommandAndRespondAsync(string requestId, string comman } catch (Exception ex) when (ex is IOException or ObjectDisposedException) { - // Connection lost — nothing we can do + // Connection lost — nothing we can do } return; } @@ -875,7 +875,7 @@ await handler(new CommandContext } catch (Exception error) when (error is not OperationCanceledException) { - // User handler can throw any exception — report the error back to the server + // User handler can throw any exception — report the error back to the server // so the pending command doesn't hang. var message = error.Message; try @@ -884,7 +884,7 @@ await handler(new CommandContext } catch (Exception ex) when (ex is IOException or ObjectDisposedException) { - // Connection lost — nothing we can do + // Connection lost — nothing we can do } } } @@ -923,7 +923,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str } catch (Exception ex) when (ex is not OperationCanceledException) { - // User handler can throw any exception — attempt to cancel so the request doesn't hang. + // User handler can throw any exception — attempt to cancel so the request doesn't hang. try { await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UIElicitationResponse @@ -933,7 +933,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str } catch (Exception innerEx) when (innerEx is IOException or ObjectDisposedException) { - // Connection lost — nothing we can do + // Connection lost — nothing we can do } } } @@ -956,7 +956,7 @@ private void AssertElicitation() /// private sealed class SessionUiApiImpl(CopilotSession session) : ISessionUiApi { - public async Task ElicitationAsync(ElicitationParams elicitationParams, CancellationToken cancellationToken) + public async Task ElicitAsync(ElicitationParams elicitationParams, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(elicitationParams); session.ThrowIfDisposed(); @@ -1040,7 +1040,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat return null; } - public async Task InputAsync(string message, InputOptions? options, CancellationToken cancellationToken) + public async Task InputAsync(string message, UiInputOptions? options, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(message); session.ThrowIfDisposed(); @@ -1316,7 +1316,7 @@ internal async Task HandleSystemMessageTransf /// /// /// - /// var events = await session.GetMessagesAsync(); + /// var events = await session.GetEventsAsync(); /// foreach (var evt in events) /// { /// if (evt is AssistantMessageEvent) @@ -1326,7 +1326,7 @@ internal async Task HandleSystemMessageTransf /// } /// /// - public async Task> GetMessagesAsync(CancellationToken cancellationToken = default) + public async Task> GetEventsAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -1451,7 +1451,7 @@ public async Task LogAsync(string message, SessionLogLevel? level = null, bool? /// /// /// - /// // Using 'await using' for automatic disposal — session can still be resumed later + /// // Using 'await using' for automatic disposal — session can still be resumed later /// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll }); /// /// // Or manually dispose diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 4ac583060..d5307022c 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -207,7 +207,7 @@ public string? GithubToken /// Custom session filesystem provider configuration. /// When set, the client registers as the session filesystem provider on connect, /// routing session-scoped file I/O through per-session handlers created via - /// or . + /// or . /// public SessionFsConfig? SessionFs { get; set; } @@ -940,7 +940,7 @@ public sealed class ElicitationResult /// /// Options for the convenience method. /// -public sealed class InputOptions +public sealed class UiInputOptions { /// Title label for the input field. public string? Title { get; set; } @@ -973,7 +973,7 @@ public interface ISessionUiApi /// Optional cancellation token. /// The with the user's response. /// Thrown if the host does not support elicitation. - Task ElicitationAsync(ElicitationParams elicitationParams, CancellationToken cancellationToken = default); + Task ElicitAsync(ElicitationParams elicitationParams, CancellationToken cancellationToken = default); /// /// Shows a confirmation dialog and returns the user's boolean answer. @@ -1005,7 +1005,7 @@ public interface ISessionUiApi /// Optional cancellation token. /// The entered string, or null if the user declined/cancelled. /// Thrown if the host does not support elicitation. - Task InputAsync(string message, InputOptions? options = null, CancellationToken cancellationToken = default); + Task InputAsync(string message, UiInputOptions? options = null, CancellationToken cancellationToken = default); } // ============================================================================ @@ -1751,7 +1751,7 @@ public sealed class ProviderConfig /// exceed this limit. /// [JsonPropertyName("maxPromptTokens")] - public int? MaxInputTokens { get; set; } + public int? MaxPromptTokens { get; set; } /// /// Overrides the resolved model's default max output tokens. When hit, the @@ -2075,16 +2075,16 @@ protected SessionConfig(SessionConfig? other) : null; Model = other.Model; ModelCapabilities = other.ModelCapabilities; - OnAutoModeSwitch = other.OnAutoModeSwitch; + OnAutoModeSwitchRequest = other.OnAutoModeSwitchRequest; OnElicitationRequest = other.OnElicitationRequest; OnEvent = other.OnEvent; - OnExitPlanMode = other.OnExitPlanMode; + OnExitPlanModeRequest = other.OnExitPlanModeRequest; OnPermissionRequest = other.OnPermissionRequest; OnUserInputRequest = other.OnUserInputRequest; Provider = other.Provider; EnableSessionTelemetry = other.EnableSessionTelemetry; ReasoningEffort = other.ReasoningEffort; - CreateSessionFsHandler = other.CreateSessionFsHandler; + CreateSessionFsProvider = other.CreateSessionFsProvider; GitHubToken = other.GitHubToken; RemoteSession = other.RemoteSession; Cloud = other.Cloud; @@ -2209,13 +2209,13 @@ protected SessionConfig(SessionConfig? other) /// Handler for exit-plan-mode requests from the server. /// When provided, the server will route exitPlanMode.request callbacks to this handler. /// - public ExitPlanModeHandler? OnExitPlanMode { get; set; } + public ExitPlanModeHandler? OnExitPlanModeRequest { get; set; } /// /// Handler for auto-mode-switch requests from the server. /// When provided, the server will route autoModeSwitch.request callbacks to this handler. /// - public AutoModeSwitchHandler? OnAutoModeSwitch { get; set; } + public AutoModeSwitchHandler? OnAutoModeSwitchRequest { get; set; } /// /// Hook handlers for session lifecycle events. @@ -2306,7 +2306,7 @@ protected SessionConfig(SessionConfig? other) /// Supplies a handler for session filesystem operations. /// This is used only when is configured. /// - public Func? CreateSessionFsHandler { get; set; } + public Func? CreateSessionFsProvider { get; set; } /// /// GitHub token for per-session authentication. @@ -2373,7 +2373,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) DefaultAgent = other.DefaultAgent; Agent = other.Agent; DisabledSkills = other.DisabledSkills is not null ? [.. other.DisabledSkills] : null; - DisableResume = other.DisableResume; + SuppressResumeEvent = other.SuppressResumeEvent; EnableConfigDiscovery = other.EnableConfigDiscovery; ContinuePendingWork = other.ContinuePendingWork; ExcludedTools = other.ExcludedTools is not null ? [.. other.ExcludedTools] : null; @@ -2386,16 +2386,16 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) : null; Model = other.Model; ModelCapabilities = other.ModelCapabilities; - OnAutoModeSwitch = other.OnAutoModeSwitch; + OnAutoModeSwitchRequest = other.OnAutoModeSwitchRequest; OnElicitationRequest = other.OnElicitationRequest; OnEvent = other.OnEvent; - OnExitPlanMode = other.OnExitPlanMode; + OnExitPlanModeRequest = other.OnExitPlanModeRequest; OnPermissionRequest = other.OnPermissionRequest; OnUserInputRequest = other.OnUserInputRequest; Provider = other.Provider; EnableSessionTelemetry = other.EnableSessionTelemetry; ReasoningEffort = other.ReasoningEffort; - CreateSessionFsHandler = other.CreateSessionFsHandler; + CreateSessionFsProvider = other.CreateSessionFsProvider; GitHubToken = other.GitHubToken; RemoteSession = other.RemoteSession; SkillDirectories = other.SkillDirectories is not null ? [.. other.SkillDirectories] : null; @@ -2499,13 +2499,13 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// Handler for exit-plan-mode requests from the server. /// When provided, the server will route exitPlanMode.request callbacks to this handler. /// - public ExitPlanModeHandler? OnExitPlanMode { get; set; } + public ExitPlanModeHandler? OnExitPlanModeRequest { get; set; } /// /// Handler for auto-mode-switch requests from the server. /// When provided, the server will route autoModeSwitch.request callbacks to this handler. /// - public AutoModeSwitchHandler? OnAutoModeSwitch { get; set; } + public AutoModeSwitchHandler? OnAutoModeSwitchRequest { get; set; } /// /// Hook handlers for session lifecycle events. @@ -2539,7 +2539,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// When true, the session.resume event is not emitted. /// Default: false (resume event is emitted). /// - public bool DisableResume { get; set; } + public bool SuppressResumeEvent { get; set; } /// /// When , instructs the runtime to continue any tool calls @@ -2627,7 +2627,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// Supplies a handler for session filesystem operations. /// This is used only when is configured. /// - public Func? CreateSessionFsHandler { get; set; } + public Func? CreateSessionFsProvider { get; set; } /// /// GitHub token for per-session authentication. diff --git a/dotnet/test/E2E/ElicitationE2ETests.cs b/dotnet/test/E2E/ElicitationE2ETests.cs index ca2714402..3af2547e3 100644 --- a/dotnet/test/E2E/ElicitationE2ETests.cs +++ b/dotnet/test/E2E/ElicitationE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -56,7 +56,7 @@ public async Task Elicitation_Throws_When_Capability_Is_Missing() ex = await Assert.ThrowsAsync(async () => { - await session.Ui.ElicitationAsync(new ElicitationParams + await session.Ui.ElicitAsync(new ElicitationParams { Message = "Enter name", RequestedSchema = new ElicitationSchema @@ -199,7 +199,7 @@ public async Task InputAsync_Returns_Freeform_Value() }, }); - var result = await session.Ui.InputAsync("Enter value", new InputOptions + var result = await session.Ui.InputAsync("Enter value", new UiInputOptions { Title = "Value", Description = "A value to test", @@ -246,9 +246,9 @@ public async Task ElicitationAsync_Returns_All_Action_Shapes() }, }; - var accept = await session.Ui.ElicitationAsync(parameters); - var decline = await session.Ui.ElicitationAsync(parameters); - var cancel = await session.Ui.ElicitationAsync(parameters); + var accept = await session.Ui.ElicitAsync(parameters); + var decline = await session.Ui.ElicitAsync(parameters); + var cancel = await session.Ui.ElicitAsync(parameters); Assert.Equal(UIElicitationResponseAction.Accept, accept.Action); Assert.Equal("Mona", accept.Content!["name"].ToString()); @@ -333,7 +333,7 @@ public void ElicitationResult_Types_Are_Properly_Structured() [Fact] public void InputOptions_Has_All_Properties() { - var options = new InputOptions + var options = new UiInputOptions { Title = "Email Address", Description = "Enter your email", diff --git a/dotnet/test/E2E/ErrorResilienceE2ETests.cs b/dotnet/test/E2E/ErrorResilienceE2ETests.cs index 4899f1386..0787b2a37 100644 --- a/dotnet/test/E2E/ErrorResilienceE2ETests.cs +++ b/dotnet/test/E2E/ErrorResilienceE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -32,7 +32,7 @@ public async Task Should_Throw_When_Getting_Messages_From_Disconnected_Session() var session = await CreateSessionAsync(); await session.DisposeAsync(); - await Assert.ThrowsAnyAsync(() => session.GetMessagesAsync()); + await Assert.ThrowsAnyAsync(() => session.GetEventsAsync()); } [Fact] diff --git a/dotnet/test/E2E/EventFidelityE2ETests.cs b/dotnet/test/E2E/EventFidelityE2ETests.cs index fa034c565..fee851c8e 100644 --- a/dotnet/test/E2E/EventFidelityE2ETests.cs +++ b/dotnet/test/E2E/EventFidelityE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -225,11 +225,11 @@ await session.SendAndWaitAsync(new MessageOptions Prompt = "Read the file 'order.txt' and tell me what the number is.", }); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); var types = messages.Select(m => m.Type).ToList(); // Verify complete event ordering contract: - // session.start → user.message → tool.execution_start → tool.execution_complete → assistant.message + // session.start → user.message → tool.execution_start → tool.execution_complete → assistant.message var sessionStartIdx = types.IndexOf("session.start"); var userMsgIdx = types.IndexOf("user.message"); var toolStartIdx = types.IndexOf("tool.execution_start"); diff --git a/dotnet/test/E2E/ModeHandlersE2ETests.cs b/dotnet/test/E2E/ModeHandlersE2ETests.cs index 0af54c4fd..3f7ec47c8 100644 --- a/dotnet/test/E2E/ModeHandlersE2ETests.cs +++ b/dotnet/test/E2E/ModeHandlersE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -28,7 +28,7 @@ public async Task Should_Invoke_Exit_Plan_Mode_Handler_When_Model_Uses_Tool() { GitHubToken = Token, OnPermissionRequest = PermissionHandler.ApproveAll, - OnExitPlanMode = (request, invocation) => + OnExitPlanModeRequest = (request, invocation) => { handlerTask.TrySetResult((request, invocation)); return Task.FromResult(new ExitPlanModeResult @@ -96,7 +96,7 @@ public async Task Should_Invoke_Auto_Mode_Switch_Handler_When_Rate_Limited() { GitHubToken = Token, OnPermissionRequest = PermissionHandler.ApproveAll, - OnAutoModeSwitch = (request, invocation) => + OnAutoModeSwitchRequest = (request, invocation) => { handlerTask.TrySetResult((request, invocation)); return Task.FromResult(AutoModeSwitchResponse.Yes); diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index 5d70f51b1..2a41b5d1e 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -133,7 +133,7 @@ public async Task Client_Receives_Commands_Changed_When_Another_Client_Joins_Wit Handler = _ => Task.CompletedTask, }, ], - DisableResume = true, + SuppressResumeEvent = true, }); var commandsChanged = await commandsChangedTcs.Task.WaitAsync(TimeSpan.FromSeconds(15)); @@ -168,7 +168,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici } }); - // Client2 joins WITH elicitation handler — triggers capabilities.changed + // Client2 joins WITH elicitation handler — triggers capabilities.changed var session2 = await Client2.ResumeSessionAsync(session1.SessionId, new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, @@ -177,7 +177,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici Action = Rpc.UIElicitationResponseAction.Accept, Content = new Dictionary(), }), - DisableResume = true, + SuppressResumeEvent = true, }); var capEvent = await capChangedTcs.Task.WaitAsync(TimeSpan.FromSeconds(15)); @@ -232,7 +232,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec Action = Rpc.UIElicitationResponseAction.Accept, Content = new Dictionary(), }), - DisableResume = true, + SuppressResumeEvent = true, }); await capEnabledTcs.Task.WaitAsync(TimeSpan.FromSeconds(15)); @@ -250,7 +250,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec } }); - // Force-stop client3 — destroys the socket, triggering server-side cleanup + // Force-stop client3 — destroys the socket, triggering server-side cleanup await _client3.ForceStopAsync(); _client3 = null; diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index fdb030f7f..7f0620976 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -452,7 +452,7 @@ private static string GetCliUrl(CopilotClient client) private static async Task GetSingleResumeEventAsync(CopilotSession session) { - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); return Assert.Single(messages.OfType()); } } diff --git a/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs b/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs index a363b5586..ef18be921 100644 --- a/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs +++ b/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -30,7 +30,7 @@ public async Task Should_Emit_Mode_Changed_Event_When_Mode_Set() session, evt => evt.Data.NewMode == SessionMode.Plan && evt.Data.PreviousMode == SessionMode.Interactive, EventTimeout, - timeoutDescription: "session.mode_changed event for interactive→plan"); + timeoutDescription: "session.mode_changed event for interactive→plan"); await session.Rpc.Mode.SetAsync(SessionMode.Plan); @@ -140,7 +140,7 @@ public async Task Should_Emit_Snapshot_Rewind_Event_And_Remove_Events_On_Truncat // gates flushing on shouldSaveSession, which flips on the first user.message). await session.SendAndWaitAsync(new MessageOptions { Prompt = "Say SNAPSHOT_REWIND_TARGET exactly." }); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); var userEvent = messages.OfType().FirstOrDefault() ?? throw new InvalidOperationException("Expected at least one user.message in persisted history"); var targetEventId = userEvent.Id.ToString(); @@ -161,7 +161,7 @@ public async Task Should_Emit_Snapshot_Rewind_Event_And_Remove_Events_On_Truncat Assert.Equal(truncateResult.EventsRemoved, (long)rewindEvent.Data.EventsRemoved); // Verify the truncated event is no longer in persisted history. - var messagesAfter = await session.GetMessagesAsync(); + var messagesAfter = await session.GetEventsAsync(); Assert.DoesNotContain(messagesAfter, e => e.Id == userEvent.Id); } @@ -172,7 +172,7 @@ public async Task Should_Allow_Session_Use_After_Truncate() await session.SendAndWaitAsync(new MessageOptions { Prompt = "Say SNAPSHOT_REWIND_TARGET exactly." }); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); var userEvent = messages.OfType().FirstOrDefault() ?? throw new InvalidOperationException("Expected at least one user.message in persisted history"); diff --git a/dotnet/test/E2E/RpcSessionStateE2ETests.cs b/dotnet/test/E2E/RpcSessionStateE2ETests.cs index ff0e9bd8f..8092bbe3e 100644 --- a/dotnet/test/E2E/RpcSessionStateE2ETests.cs +++ b/dotnet/test/E2E/RpcSessionStateE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -252,7 +252,7 @@ public async Task Should_Fork_Session_With_Persisted_Messages() var initialAnswer = await session.SendAndWaitAsync(new MessageOptions { Prompt = sourcePrompt }); Assert.Contains("FORK_SOURCE_ALPHA", initialAnswer?.Data.Content ?? string.Empty); - var sourceConversation = GetConversationMessages(await session.GetMessagesAsync()); + var sourceConversation = GetConversationMessages(await session.GetEventsAsync()); Assert.Contains(sourceConversation, message => message.Role == "user" && message.Content == sourcePrompt); Assert.Contains(sourceConversation, message => message.Role == "assistant" && message.Content.Contains("FORK_SOURCE_ALPHA", StringComparison.Ordinal)); @@ -261,16 +261,16 @@ public async Task Should_Fork_Session_With_Persisted_Messages() Assert.NotEqual(session.SessionId, fork.SessionId); await using var forkedSession = await ResumeSessionAsync(fork.SessionId); - var forkedConversation = GetConversationMessages(await forkedSession.GetMessagesAsync()); + var forkedConversation = GetConversationMessages(await forkedSession.GetEventsAsync()); Assert.Equal(sourceConversation, forkedConversation.Take(sourceConversation.Count)); var forkAnswer = await forkedSession.SendAndWaitAsync(new MessageOptions { Prompt = forkPrompt }); Assert.Contains("FORK_CHILD_BETA", forkAnswer?.Data.Content ?? string.Empty); - var sourceAfterFork = GetConversationMessages(await session.GetMessagesAsync()); + var sourceAfterFork = GetConversationMessages(await session.GetEventsAsync()); Assert.DoesNotContain(sourceAfterFork, message => message.Content == forkPrompt); - var forkAfterPrompt = GetConversationMessages(await forkedSession.GetMessagesAsync()); + var forkAfterPrompt = GetConversationMessages(await forkedSession.GetEventsAsync()); Assert.Contains(forkAfterPrompt, message => message.Role == "user" && message.Content == forkPrompt); Assert.Contains(forkAfterPrompt, message => message.Role == "assistant" && message.Content.Contains("FORK_CHILD_BETA", StringComparison.Ordinal)); } @@ -298,7 +298,7 @@ public async Task Should_Handle_Forking_Session_Without_Persisted_Events() Assert.NotEqual(session.SessionId, forkSessionId); await using var forkedSession = await ResumeSessionAsync(forkSessionId); - Assert.Empty(GetConversationMessages(await forkedSession.GetMessagesAsync())); + Assert.Empty(GetConversationMessages(await forkedSession.GetEventsAsync())); } [Fact] @@ -311,7 +311,7 @@ public async Task Should_Fork_Session_To_Event_Id_Excluding_Boundary_Event() await session.SendAndWaitAsync(new MessageOptions { Prompt = firstPrompt }); await session.SendAndWaitAsync(new MessageOptions { Prompt = secondPrompt }); - var sourceEvents = await session.GetMessagesAsync(); + var sourceEvents = await session.GetEventsAsync(); var secondUserEvent = sourceEvents .OfType() .FirstOrDefault(e => string.Equals(e.Data.Content, secondPrompt, StringComparison.Ordinal)) @@ -325,7 +325,7 @@ public async Task Should_Fork_Session_To_Event_Id_Excluding_Boundary_Event() Assert.NotEqual(session.SessionId, fork.SessionId); await using var forkedSession = await ResumeSessionAsync(fork.SessionId); - var forkedEvents = await forkedSession.GetMessagesAsync(); + var forkedEvents = await forkedSession.GetEventsAsync(); Assert.DoesNotContain(forkedEvents, e => e.Id == secondUserEvent.Id); var forkedConversation = GetConversationMessages(forkedEvents); diff --git a/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs b/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs index ee9ebb27d..50e2d366f 100644 --- a/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs +++ b/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -118,7 +118,7 @@ private static async Task> WaitForMessagesAsync( await TestHelper.WaitForConditionAsync( async () => { - messages = (await session.GetMessagesAsync()).ToList(); + messages = (await session.GetEventsAsync()).ToList(); return predicate(messages); }, timeout: TimeSpan.FromSeconds(120), diff --git a/dotnet/test/E2E/SessionConfigE2ETests.cs b/dotnet/test/E2E/SessionConfigE2ETests.cs index 43d6681b7..d269fd092 100644 --- a/dotnet/test/E2E/SessionConfigE2ETests.cs +++ b/dotnet/test/E2E/SessionConfigE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -34,7 +34,7 @@ public async Task Vision_Disabled_Then_Enabled_Via_SetModel() }, }); - // Turn 1: vision off — no image_url expected + // Turn 1: vision off — no image_url expected await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT1 = await Ctx.GetExchangesAsync(); var t1Messages = trafficAfterT1.SelectMany(e => e.Request.Messages).ToList(); @@ -49,7 +49,7 @@ await session.SetModelAsync( Supports = new ModelCapabilitiesOverrideSupports { Vision = true }, }); - // Turn 2: vision on — image_url expected + // Turn 2: vision on — image_url expected await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT2 = await Ctx.GetExchangesAsync(); var newExchanges = trafficAfterT2.Skip(trafficAfterT1.Count).ToList(); @@ -74,7 +74,7 @@ public async Task Vision_Enabled_Then_Disabled_Via_SetModel() }, }); - // Turn 1: vision on — image_url expected + // Turn 1: vision on — image_url expected await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT1 = await Ctx.GetExchangesAsync(); var t1Messages = trafficAfterT1.SelectMany(e => e.Request.Messages).ToList(); @@ -89,7 +89,7 @@ await session.SetModelAsync( Supports = new ModelCapabilitiesOverrideSupports { Vision = false }, }); - // Turn 2: vision off — no image_url expected in new exchanges + // Turn 2: vision off — no image_url expected in new exchanges await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT2 = await Ctx.GetExchangesAsync(); var newExchanges = trafficAfterT2.Skip(trafficAfterT1.Count).ToList(); @@ -112,7 +112,7 @@ public async Task Should_Use_Custom_SessionId() Assert.Equal(requestedSessionId, session.SessionId); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); var startEvent = Assert.IsType(messages[0]); Assert.Equal(requestedSessionId, startEvent.Data.SessionId); @@ -131,7 +131,7 @@ public async Task Should_Apply_ReasoningEffort_On_Session_Create() ReasoningEffort = "high", }); - var startEvent = Assert.Single((await session.GetMessagesAsync()).OfType()); + var startEvent = Assert.Single((await session.GetEventsAsync()).OfType()); Assert.Equal(reasoningModelId, startEvent.Data.SelectedModel); Assert.Equal("high", startEvent.Data.ReasoningEffort); @@ -153,7 +153,7 @@ public async Task Should_Apply_All_ReasoningEffort_Values_On_Session_Create(stri ReasoningEffort = effort, }); - var startEvent = Assert.Single((await session.GetMessagesAsync()).OfType()); + var startEvent = Assert.Single((await session.GetEventsAsync()).OfType()); Assert.Equal(reasoningModelId, startEvent.Data.SelectedModel); Assert.Equal(effort, startEvent.Data.ReasoningEffort); @@ -172,7 +172,7 @@ public async Task Should_Apply_ReasoningEffort_On_Session_Resume() ReasoningEffort = "high", }); - var resumeEvent = Assert.Single((await resumedSession.GetMessagesAsync()).OfType()); + var resumeEvent = Assert.Single((await resumedSession.GetEventsAsync()).OfType()); Assert.Equal(reasoningModelId, resumeEvent.Data.SelectedModel); Assert.Equal("high", resumeEvent.Data.ReasoningEffort); diff --git a/dotnet/test/E2E/SessionE2ETests.cs b/dotnet/test/E2E/SessionE2ETests.cs index e46581249..7c57a3ad8 100644 --- a/dotnet/test/E2E/SessionE2ETests.cs +++ b/dotnet/test/E2E/SessionE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -21,14 +21,14 @@ public async Task ShouldCreateAndDisconnectSessions() Assert.Matches(@"^[a-f0-9-]+$", session.SessionId); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); Assert.NotEmpty(messages); var startEvent = Assert.IsType(messages[0]); Assert.Equal(session.SessionId, startEvent.Data.SessionId); await session.DisposeAsync(); - await Assert.ThrowsAsync(() => session.GetMessagesAsync()); + await Assert.ThrowsAsync(() => session.GetEventsAsync()); } [Fact] @@ -243,7 +243,7 @@ public async Task Should_Resume_A_Session_Using_A_New_Client() }); Assert.Equal(sessionId, session2.SessionId); - var messages = await session2.GetMessagesAsync(); + var messages = await session2.GetEventsAsync(); Assert.Contains(messages, m => m is UserMessageEvent); var resumeEvent = Assert.Single(messages.OfType()); Assert.True(resumeEvent.Data.ContinuePendingWork); @@ -284,7 +284,7 @@ await session.SendAsync(new MessageOptions await sessionIdleTask; // The session should still be alive and usable after abort - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); Assert.NotEmpty(messages); // Verify an abort event exists in messages @@ -371,7 +371,7 @@ public async Task Should_Receive_Session_Events() Assert.Contains(observedEvents, evt => evt is AssistantMessageEvent); Assert.Contains(observedEvents, evt => evt is SessionIdleEvent); - // Events must be dispatched serially — never more than one handler invocation at a time. + // Events must be dispatched serially — never more than one handler invocation at a time. Assert.Equal(1, maxConcurrent); // Verify the assistant response contains the expected answer. @@ -670,7 +670,7 @@ public async Task DisposeAsync_From_Handler_Does_Not_Deadlock() { if (evt is UserMessageEvent) { - // Call DisposeAsync from within a handler — must not deadlock. + // Call DisposeAsync from within a handler — must not deadlock. session.DisposeAsync().AsTask().ContinueWith(_ => disposed.TrySetResult()); } }); @@ -728,7 +728,7 @@ await session.SendAndWaitAsync(new MessageOptions ], }); - var userMessage = (await session.GetMessagesAsync()).OfType().Last(); + var userMessage = (await session.GetEventsAsync()).OfType().Last(); var attachment = Assert.IsType(Assert.Single(userMessage.Data.Attachments!)); Assert.Equal("attached-file.txt", attachment.DisplayName); Assert.Equal(filePath, attachment.Path); @@ -758,7 +758,7 @@ await session.SendAndWaitAsync(new MessageOptions ], }); - var userMessage = (await session.GetMessagesAsync()).OfType().Last(); + var userMessage = (await session.GetEventsAsync()).OfType().Last(); var attachment = Assert.IsType(Assert.Single(userMessage.Data.Attachments!)); Assert.Equal("attached-directory", attachment.DisplayName); Assert.Equal(directoryPath, attachment.Path); @@ -791,7 +791,7 @@ await session.SendAndWaitAsync(new MessageOptions ], }); - var userMessage = (await session.GetMessagesAsync()).OfType().Last(); + var userMessage = (await session.GetEventsAsync()).OfType().Last(); var attachment = Assert.IsType(Assert.Single(userMessage.Data.Attachments!)); Assert.Equal("selected-file.cs", attachment.DisplayName); Assert.Equal(filePath, attachment.FilePath); @@ -823,7 +823,7 @@ await session.SendAndWaitAsync(new MessageOptions ], }); - var userMessage = (await session.GetMessagesAsync()).OfType().Last(); + var userMessage = (await session.GetEventsAsync()).OfType().Last(); var attachment = Assert.IsType(Assert.Single(userMessage.Data.Attachments!)); Assert.Equal(1234, attachment.Number); Assert.Equal(UserMessageAttachmentGithubReferenceType.Issue, attachment.ReferenceType); @@ -843,7 +843,7 @@ await session.SendAndWaitAsync(new MessageOptions Mode = "plan", }); - var userMessage = (await session.GetMessagesAsync()).OfType().Last(); + var userMessage = (await session.GetEventsAsync()).OfType().Last(); Assert.Equal("Say mode ok.", userMessage.Data.Content); // The current runtime accepts the per-message mode option but does not echo it on user.message. Assert.Null(userMessage.Data.AgentMode); diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index 3a5a03cf0..f56da98b0 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -31,7 +31,7 @@ public async Task Should_Route_File_Operations_Through_The_Session_Fs_Provider() var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => new TestSessionFsHandler(s.SessionId, providerRoot), + CreateSessionFsProvider = s => new TestSessionFsHandler(s.SessionId, providerRoot), }); var msg = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 100 + 200?" }); @@ -61,7 +61,7 @@ public async Task Should_Load_Session_Data_From_Fs_Provider_On_Resume() var session1 = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = createSessionFsHandler, + CreateSessionFsProvider = createSessionFsHandler, }); var sessionId = session1.SessionId; @@ -75,7 +75,7 @@ public async Task Should_Load_Session_Data_From_Fs_Provider_On_Resume() var session2 = await client.ResumeSessionAsync(sessionId, new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = createSessionFsHandler, + CreateSessionFsProvider = createSessionFsHandler, }); var msg2 = await session2.SendAndWaitAsync(new MessageOptions { Prompt = "What is that times 3?" }); @@ -100,7 +100,7 @@ public async Task Should_Reject_SetProvider_When_Sessions_Already_Exist() _ = await client1.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = createSessionFsHandler, + CreateSessionFsProvider = createSessionFsHandler, }); var port = client1.ActualPort @@ -324,7 +324,7 @@ public async Task Should_Map_Large_Output_Handling_Into_SessionFs() var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => new TestSessionFsHandler(s.SessionId, providerRoot), + CreateSessionFsProvider = s => new TestSessionFsHandler(s.SessionId, providerRoot), Tools = [ AIFunctionFactory.Create(() => suppliedFileContent, "get_big_string", "Returns a large string") @@ -336,7 +336,7 @@ await session.SendAndWaitAsync(new MessageOptions Prompt = "Call the get_big_string tool and reply with the word DONE only.", }); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); var toolResult = FindToolCallResult(messages, "get_big_string"); Assert.NotNull(toolResult); Assert.Contains($"{SessionFsConfig.SessionStatePath}/temp/", toolResult); @@ -366,7 +366,7 @@ public async Task Should_Succeed_With_Compaction_While_Using_SessionFs() var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => new TestSessionFsHandler(s.SessionId, providerRoot), + CreateSessionFsProvider = s => new TestSessionFsHandler(s.SessionId, providerRoot), }); SessionCompactionCompleteEvent? compactionEvent = null; @@ -405,7 +405,7 @@ public async Task Should_Write_Workspace_Metadata_Via_SessionFs() var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => new TestSessionFsHandler(s.SessionId, providerRoot), + CreateSessionFsProvider = s => new TestSessionFsHandler(s.SessionId, providerRoot), }); var msg = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 7 * 8?" }); @@ -436,7 +436,7 @@ public async Task Should_Persist_Plan_Md_Via_SessionFs() var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => new TestSessionFsHandler(s.SessionId, providerRoot), + CreateSessionFsProvider = s => new TestSessionFsHandler(s.SessionId, providerRoot), }); // Write a plan via the session RPC diff --git a/dotnet/test/E2E/SessionFsSqliteE2ETests.cs b/dotnet/test/E2E/SessionFsSqliteE2ETests.cs index f495fca3d..cdb9873aa 100644 --- a/dotnet/test/E2E/SessionFsSqliteE2ETests.cs +++ b/dotnet/test/E2E/SessionFsSqliteE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -30,7 +30,7 @@ public async Task Should_Route_Sql_Queries_Through_The_Sessionfs_Sqlite_Handler( var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => new InMemorySessionFsSqliteHandler(s.SessionId, _sqliteCalls), + CreateSessionFsProvider = s => new InMemorySessionFsSqliteHandler(s.SessionId, _sqliteCalls), }); var msg = await session.SendAndWaitAsync(new MessageOptions @@ -60,7 +60,7 @@ public async Task Should_Allow_Subagents_To_Use_Sql_Tool_Via_Inherited_Sessionfs var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, - CreateSessionFsHandler = s => + CreateSessionFsProvider = s => { handler = new InMemorySessionFsSqliteHandler(s.SessionId, _sqliteCalls); return handler; diff --git a/dotnet/test/E2E/SessionLifecycleE2ETests.cs b/dotnet/test/E2E/SessionLifecycleE2ETests.cs index 19134cb53..f35ade93d 100644 --- a/dotnet/test/E2E/SessionLifecycleE2ETests.cs +++ b/dotnet/test/E2E/SessionLifecycleE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -84,7 +84,7 @@ await session.SendAndWaitAsync(new MessageOptions Prompt = "What is 2+2? Reply with just the number.", }); - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); Assert.NotEmpty(messages); // Should have at least session.start, user.message, assistant.message diff --git a/dotnet/test/E2E/StreamingFidelityE2ETests.cs b/dotnet/test/E2E/StreamingFidelityE2ETests.cs index 82580a656..7f7847b99 100644 --- a/dotnet/test/E2E/StreamingFidelityE2ETests.cs +++ b/dotnet/test/E2E/StreamingFidelityE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -142,7 +142,7 @@ public async Task Should_Not_Produce_Deltas_After_Session_Resume_With_Streaming_ public async Task Should_Emit_Streaming_Deltas_With_Reasoning_Effort_Configured() { // Verifies that setting ReasoningEffort alongside Streaming=true does not break - // the streaming pipeline — deltas still arrive and complete successfully. + // the streaming pipeline — deltas still arrive and complete successfully. var session = await CreateSessionAsync(new SessionConfig { Streaming = true, @@ -167,7 +167,7 @@ public async Task Should_Emit_Streaming_Deltas_With_Reasoning_Effort_Configured( Assert.Contains("255", assistantEvents.Last().Data.Content ?? string.Empty); // Verify the session was created with reasoning effort via GetMessages - var messages = await session.GetMessagesAsync(); + var messages = await session.GetEventsAsync(); var startEvent = Assert.Single(messages.OfType()); Assert.Equal("high", startEvent.Data.ReasoningEffort); diff --git a/dotnet/test/Harness/TestHelper.cs b/dotnet/test/Harness/TestHelper.cs index 1afd21d3c..ee3e4b159 100644 --- a/dotnet/test/Harness/TestHelper.cs +++ b/dotnet/test/Harness/TestHelper.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -21,7 +21,7 @@ public static class TestHelper var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var cts = new CancellationTokenSource(timeout ?? DefaultEventTimeout); - // Both `finalAssistantMessage` and `sawIdle` are set from two threads — the + // Both `finalAssistantMessage` and `sawIdle` are set from two threads — the // subscription callback (CLI read loop) and CheckExistingMessages (RPC reply). // We complete only once we've observed both, regardless of which path saw which. var stateLock = new object(); @@ -91,7 +91,7 @@ async void CheckExistingMessages() private static async Task<(AssistantMessageEvent? Final, bool SawIdle)> GetExistingMessagesAsync(CopilotSession session, bool alreadyIdle) { - var messages = (await session.GetMessagesAsync()).ToList(); + var messages = (await session.GetEventsAsync()).ToList(); var lastUserIdx = messages.FindLastIndex(m => m is UserMessageEvent); var currentTurn = lastUserIdx < 0 ? messages : messages.Skip(lastUserIdx).ToList(); diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 0816da9b2..57e2d873e 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -109,8 +109,8 @@ public void SessionConfig_Clone_CopiesAllProperties() SkillDirectories = ["/skills"], InstructionDirectories = ["/instructions"], DisabledSkills = ["skill1"], - OnExitPlanMode = static (_, _) => Task.FromResult(new ExitPlanModeResult()), - OnAutoModeSwitch = static (_, _) => Task.FromResult(AutoModeSwitchResponse.No), + OnExitPlanModeRequest = static (_, _) => Task.FromResult(new ExitPlanModeResult()), + OnAutoModeSwitchRequest = static (_, _) => Task.FromResult(AutoModeSwitchResponse.No), }; var clone = original.Clone(); @@ -135,8 +135,8 @@ public void SessionConfig_Clone_CopiesAllProperties() Assert.Equal(original.SkillDirectories, clone.SkillDirectories); Assert.Equal(original.InstructionDirectories, clone.InstructionDirectories); Assert.Equal(original.DisabledSkills, clone.DisabledSkills); - Assert.Same(original.OnExitPlanMode, clone.OnExitPlanMode); - Assert.Same(original.OnAutoModeSwitch, clone.OnAutoModeSwitch); + Assert.Same(original.OnExitPlanModeRequest, clone.OnExitPlanModeRequest); + Assert.Same(original.OnAutoModeSwitchRequest, clone.OnAutoModeSwitchRequest); } [Fact] @@ -315,14 +315,14 @@ public void ResumeSessionConfig_Clone_CopiesModeSwitchHandlers() { var original = new ResumeSessionConfig { - OnExitPlanMode = static (_, _) => Task.FromResult(new ExitPlanModeResult()), - OnAutoModeSwitch = static (_, _) => Task.FromResult(AutoModeSwitchResponse.No), + OnExitPlanModeRequest = static (_, _) => Task.FromResult(new ExitPlanModeResult()), + OnAutoModeSwitchRequest = static (_, _) => Task.FromResult(AutoModeSwitchResponse.No), }; var clone = original.Clone(); - Assert.Same(original.OnExitPlanMode, clone.OnExitPlanMode); - Assert.Same(original.OnAutoModeSwitch, clone.OnAutoModeSwitch); + Assert.Same(original.OnExitPlanModeRequest, clone.OnExitPlanModeRequest); + Assert.Same(original.OnAutoModeSwitchRequest, clone.OnAutoModeSwitchRequest); } [Fact] diff --git a/dotnet/test/Unit/SerializationTests.cs b/dotnet/test/Unit/SerializationTests.cs index 1ca6562f8..dc6f4e0c3 100644 --- a/dotnet/test/Unit/SerializationTests.cs +++ b/dotnet/test/Unit/SerializationTests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -26,7 +26,7 @@ public void ProviderConfig_CanSerializeHeaders_WithSdkOptions() Headers = new Dictionary { ["Authorization"] = "Bearer provider-token" }, ModelId = "gpt-4o", WireModel = "my-finetune-v3", - MaxInputTokens = 100_000, + MaxPromptTokens = 100_000, MaxOutputTokens = 4096 }; @@ -46,7 +46,7 @@ public void ProviderConfig_CanSerializeHeaders_WithSdkOptions() Assert.Equal("Bearer provider-token", deserialized.Headers!["Authorization"]); Assert.Equal("gpt-4o", deserialized.ModelId); Assert.Equal("my-finetune-v3", deserialized.WireModel); - Assert.Equal(100_000, deserialized.MaxInputTokens); + Assert.Equal(100_000, deserialized.MaxPromptTokens); Assert.Equal(4096, deserialized.MaxOutputTokens); } From 7b07d6f33d5c5aa21043d983eef88aa169ad57c2 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 13:57:01 +0100 Subject: [PATCH 04/40] Phase 4b: expand SessionFsProvider abbreviations Per ApiView #278: - RmAsync -> RemoveAsync - MkdirAsync -> MakeDirectoryAsync - ReaddirAsync -> ReadDirectoryAsync - ReaddirWithTypesAsync -> ReadDirectoryWithTypesAsync Applied to the consumer-facing protected abstract methods on SessionFsProvider. The generated ISessionFsHandler interface keeps the original RPC-style names; SessionFsProvider's explicit interface impls bridge to the new spelled-out method names. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/SessionFsProvider.cs | 18 +++++++++--------- .../test/E2E/InMemorySessionFsSqliteHandler.cs | 10 +++++----- dotnet/test/E2E/SessionFsE2ETests.cs | 16 ++++++++-------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/dotnet/src/SessionFsProvider.cs b/dotnet/src/SessionFsProvider.cs index a48033f07..7ab8bf81b 100644 --- a/dotnet/src/SessionFsProvider.cs +++ b/dotnet/src/SessionFsProvider.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -100,24 +100,24 @@ public abstract class SessionFsProvider : ISessionFsHandler /// Whether to create parent directories. /// Optional POSIX-style permission mode (e.g., 0x1FF for 0777). Null means use OS default. /// Cancellation token. - protected abstract Task MkdirAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken); + protected abstract Task MakeDirectoryAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken); /// Lists entry names in a directory. Throw if the directory does not exist. /// SessionFs-relative path. /// Cancellation token. - protected abstract Task> ReaddirAsync(string path, CancellationToken cancellationToken); + protected abstract Task> ReadDirectoryAsync(string path, CancellationToken cancellationToken); /// Lists entries with type info in a directory. Throw if the directory does not exist. /// SessionFs-relative path. /// Cancellation token. - protected abstract Task> ReaddirWithTypesAsync(string path, CancellationToken cancellationToken); + protected abstract Task> ReadDirectoryWithTypesAsync(string path, CancellationToken cancellationToken); /// Removes a file or directory. Throw if the path does not exist (unless is true). /// SessionFs-relative path. /// Whether to remove directory contents recursively. /// If true, do not throw when the path does not exist. /// Cancellation token. - protected abstract Task RmAsync(string path, bool recursive, bool force, CancellationToken cancellationToken); + protected abstract Task RemoveAsync(string path, bool recursive, bool force, CancellationToken cancellationToken); /// Renames/moves a file or directory. /// Source path. @@ -207,7 +207,7 @@ async Task ISessionFsHandler.StatAsync(SessionFsStatRequest try { - await MkdirAsync(request.Path, request.Recursive ?? false, (int?)request.Mode, cancellationToken).ConfigureAwait(false); + await MakeDirectoryAsync(request.Path, request.Recursive ?? false, (int?)request.Mode, cancellationToken).ConfigureAwait(false); return null; } catch (Exception ex) @@ -222,7 +222,7 @@ async Task ISessionFsHandler.ReaddirAsync(SessionFsReadd try { - var entries = await ReaddirAsync(request.Path, cancellationToken).ConfigureAwait(false); + var entries = await ReadDirectoryAsync(request.Path, cancellationToken).ConfigureAwait(false); return new SessionFsReaddirResult { Entries = entries }; } catch (Exception ex) @@ -237,7 +237,7 @@ async Task ISessionFsHandler.ReaddirWithTypesAs try { - var entries = await ReaddirWithTypesAsync(request.Path, cancellationToken).ConfigureAwait(false); + var entries = await ReadDirectoryWithTypesAsync(request.Path, cancellationToken).ConfigureAwait(false); return new SessionFsReaddirWithTypesResult { Entries = entries }; } catch (Exception ex) @@ -252,7 +252,7 @@ async Task ISessionFsHandler.ReaddirWithTypesAs try { - await RmAsync(request.Path, request.Recursive ?? false, request.Force ?? false, cancellationToken).ConfigureAwait(false); + await RemoveAsync(request.Path, request.Recursive ?? false, request.Force ?? false, cancellationToken).ConfigureAwait(false); return null; } catch (Exception ex) diff --git a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs index cdf5f5205..965cce6b7 100644 --- a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs +++ b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -174,19 +174,19 @@ protected override Task StatAsync(string path, Cancellation throw new FileNotFoundException($"Path does not exist: {path}"); } - protected override Task MkdirAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken) + protected override Task MakeDirectoryAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken) { _directories[Resolve(path)] = 0; return Task.CompletedTask; } - protected override Task> ReaddirAsync(string path, CancellationToken cancellationToken) + protected override Task> ReadDirectoryAsync(string path, CancellationToken cancellationToken) => Task.FromResult>([]); - protected override Task> ReaddirWithTypesAsync(string path, CancellationToken cancellationToken) + protected override Task> ReadDirectoryWithTypesAsync(string path, CancellationToken cancellationToken) => Task.FromResult>([]); - protected override Task RmAsync(string path, bool recursive, bool force, CancellationToken cancellationToken) + protected override Task RemoveAsync(string path, bool recursive, bool force, CancellationToken cancellationToken) { var key = Resolve(path); Files.TryRemove(key, out _); diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index f56da98b0..bc974a09d 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -593,16 +593,16 @@ protected override Task ExistsAsync(string path, CancellationToken cancell protected override Task StatAsync(string path, CancellationToken cancellationToken) => Task.FromException(exception); - protected override Task MkdirAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken) => + protected override Task MakeDirectoryAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken) => Task.FromException(exception); - protected override Task> ReaddirAsync(string path, CancellationToken cancellationToken) => + protected override Task> ReadDirectoryAsync(string path, CancellationToken cancellationToken) => Task.FromException>(exception); - protected override Task> ReaddirWithTypesAsync(string path, CancellationToken cancellationToken) => + protected override Task> ReadDirectoryWithTypesAsync(string path, CancellationToken cancellationToken) => Task.FromException>(exception); - protected override Task RmAsync(string path, bool recursive, bool force, CancellationToken cancellationToken) => + protected override Task RemoveAsync(string path, bool recursive, bool force, CancellationToken cancellationToken) => Task.FromException(exception); protected override Task RenameAsync(string src, string dest, CancellationToken cancellationToken) => @@ -674,13 +674,13 @@ protected override Task StatAsync(string path, Cancellation }); } - protected override Task MkdirAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken) + protected override Task MakeDirectoryAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken) { Directory.CreateDirectory(ResolvePath(path)); return Task.CompletedTask; } - protected override Task> ReaddirAsync(string path, CancellationToken cancellationToken) + protected override Task> ReadDirectoryAsync(string path, CancellationToken cancellationToken) { IList entries = Directory .EnumerateFileSystemEntries(ResolvePath(path)) @@ -691,7 +691,7 @@ protected override Task> ReaddirAsync(string path, CancellationTok return Task.FromResult(entries); } - protected override Task> ReaddirWithTypesAsync(string path, CancellationToken cancellationToken) + protected override Task> ReadDirectoryWithTypesAsync(string path, CancellationToken cancellationToken) { IList entries = Directory .EnumerateFileSystemEntries(ResolvePath(path)) @@ -704,7 +704,7 @@ protected override Task> ReaddirWithTypesA return Task.FromResult(entries); } - protected override Task RmAsync(string path, bool recursive, bool force, CancellationToken cancellationToken) + protected override Task RemoveAsync(string path, bool recursive, bool force, CancellationToken cancellationToken) { var fullPath = ResolvePath(path); From 69fccdf5092f7b39878ec6d17303dffe2725b078 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 14:08:39 +0100 Subject: [PATCH 05/40] Phase 4c: shape changes (Streaming, Tools, ToolBinaryResultType, cleanups) - (Resume)SessionConfig.Streaming: bool -> bool? (JsonIgnore WhenWritingNull) - McpServerConfig.Tools: IList -> IList? (null = include all, empty = include none); auto-init removed - ToolBinaryResult.Type: bare string -> string-backed struct ToolBinaryResultType with well-known Image / Resource values - Remove obsolete redirects: - CopilotClientOptions.GithubToken / .AutoRestart - PermissionRequestResultKind.DeniedInteractivelyByUser / DeniedCouldNotRequestFromUser / DeniedByRules - Remove CopilotClientOptions.AutoStart (auto-start always on; consumer can still call StartAsync explicitly) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Client.cs | 12 +- dotnet/src/Types.cs | 126 +++++++++++------- dotnet/test/E2E/ClientOptionsE2ETests.cs | 49 ++----- dotnet/test/E2E/ToolsE2ETests.cs | 2 +- dotnet/test/Unit/CloneTests.cs | 6 +- .../Unit/PermissionRequestResultKindTests.cs | 7 - dotnet/test/Unit/SerializationTests.cs | 2 +- 7 files changed, 93 insertions(+), 111 deletions(-) diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index efcbc0eef..bb27cf78f 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -92,7 +92,7 @@ public sealed partial class CopilotClient : IDisposable, IAsyncDisposable /// Gets the typed RPC client for server-scoped methods (no session required). /// /// - /// The client must be started before accessing this property. Use or set to true. + /// The client must be started before accessing this property. Call before use. /// /// Thrown if the client has been disposed. /// Thrown if the client is not started. @@ -214,12 +214,11 @@ private static Uri ParseCliUrl(string url) /// If connecting to an external server (via CliUrl), only establishes the connection. /// /// - /// This method is called automatically when creating a session if is true (default). /// /// /// /// - /// var client = new CopilotClient(new CopilotClientOptions { AutoStart = false }); + /// var client = new CopilotClient(); /// await client.StartAsync(); /// // Now ready to create sessions /// @@ -522,7 +521,7 @@ private static (SystemMessageConfig? wireConfig, DictionaryA task that resolves to provide the . /// /// Sessions maintain conversation state, handle events, and manage tool execution. - /// If the client is not connected and is enabled (default), + /// If the client is not connected, /// this will automatically start the connection. /// /// @@ -1309,11 +1308,6 @@ private static IOException CreateCliExitedException(string message, StringBuilde private Task EnsureConnectedAsync(CancellationToken cancellationToken) { - if (_connectionTask is null && !_options.AutoStart) - { - throw new InvalidOperationException($"Client not connected. Call {nameof(StartAsync)}() first."); - } - // If already started or starting, this will return the existing task return (Task)StartAsync(cancellationToken); } diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index d5307022c..5814d4a54 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -87,10 +87,6 @@ protected CopilotClientOptions(CopilotClientOptions? other) { if (other is null) return; - AutoStart = other.AutoStart; -#pragma warning disable CS0618 // Obsolete member - AutoRestart = other.AutoRestart; -#pragma warning restore CS0618 CliArgs = (string[]?)other.CliArgs?.Clone(); CliPath = other.CliPath; CliUrl = other.CliUrl; @@ -151,16 +147,6 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// public string LogLevel { get; set; } = "info"; /// - /// Whether to automatically start the CLI server if it is not already running. - /// - public bool AutoStart { get; set; } = true; - /// - /// Obsolete. This option has no effect. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("AutoRestart has no effect and will be removed in a future release.")] - public bool AutoRestart { get; set; } - /// /// Environment variables to pass to the CLI process. /// public IReadOnlyDictionary? Environment { get; set; } @@ -176,17 +162,6 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// public string? GitHubToken { get; set; } - /// - /// Obsolete. Use instead. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Use GitHubToken instead.", error: false)] - public string? GithubToken - { - get => GitHubToken; - set => GitHubToken = value; - } - /// /// Whether to use the logged-in user for authentication. /// When true, the CLI server will attempt to use stored OAuth tokens or gh CLI auth. @@ -350,10 +325,11 @@ public sealed class ToolBinaryResult public string MimeType { get; set; } = string.Empty; /// - /// Type identifier for the binary result. + /// Type identifier for the binary result. Use the well-known values on + /// ("image", "resource"). /// [JsonPropertyName("type")] - public string Type { get; set; } = string.Empty; + public ToolBinaryResultType Type { get; set; } /// /// Optional human-readable description of the binary result. @@ -362,6 +338,72 @@ public sealed class ToolBinaryResult public string? Description { get; set; } } +/// Describes the kind of a . +[JsonConverter(typeof(ToolBinaryResultType.Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ToolBinaryResultType : IEquatable +{ + /// Gets the kind indicating an inline image result. + public static ToolBinaryResultType Image { get; } = new("image"); + + /// Gets the kind indicating an MCP resource result. + public static ToolBinaryResultType Resource { get; } = new("resource"); + + /// Gets the underlying string value of this . + public string Value => _value ?? string.Empty; + + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The string value for this type. + [JsonConstructor] + public ToolBinaryResultType(string value) => _value = value; + + /// + public static bool operator ==(ToolBinaryResultType left, ToolBinaryResultType right) => left.Equals(right); + + /// + public static bool operator !=(ToolBinaryResultType left, ToolBinaryResultType right) => !left.Equals(right); + + /// + public override bool Equals([NotNullWhen(true)] object? obj) => obj is ToolBinaryResultType other && Equals(other); + + /// + public bool Equals(ToolBinaryResultType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ToolBinaryResultType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.String) + { + throw new JsonException("Expected string for ToolBinaryResultType."); + } + + var value = reader.GetString(); + if (value is null) + { + throw new JsonException("ToolBinaryResultType value cannot be null."); + } + + return new ToolBinaryResultType(value); + } + + /// + public override void Write(Utf8JsonWriter writer, ToolBinaryResultType value, JsonSerializerOptions options) => + writer.WriteStringValue(value.Value); + } +} + /// /// Represents the structured result of a tool execution. /// @@ -477,7 +519,7 @@ private static ToolResultObject ConvertAIContents(IEnumerable content { Data = dataContent.Base64Data.ToString(), MimeType = dataContent.MediaType ?? "application/octet-stream", - Type = dataContent.HasTopLevelMediaType("image") ? "image" : "resource", + Type = dataContent.HasTopLevelMediaType("image") ? ToolBinaryResultType.Image : ToolBinaryResultType.Resource, }); break; @@ -544,21 +586,6 @@ public sealed class ToolInvocation /// Gets the kind indicating no permission decision was made. public static PermissionRequestResultKind NoResult { get; } = new("no-result"); - /// Deprecated. Use instead. - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Use Rejected instead.")] - public static PermissionRequestResultKind DeniedInteractivelyByUser => Rejected; - - /// Deprecated. Use instead. - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Use UserNotAvailable instead.")] - public static PermissionRequestResultKind DeniedCouldNotRequestFromUser => UserNotAvailable; - - /// Deprecated. Use instead. - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Use UserNotAvailable instead.")] - public static PermissionRequestResultKind DeniedByRules => UserNotAvailable; - /// Gets the underlying string value of this . public string Value => _value ?? string.Empty; @@ -1805,10 +1832,12 @@ public abstract class McpServerConfig private protected McpServerConfig() { } /// - /// List of tools to include from this server. Empty list means none. Use "*" for all. + /// List of tools to include from this server. null (the default) + /// means include all tools. An empty list means include none. /// [JsonPropertyName("tools")] - public IList Tools { get => field ??= []; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public IList? Tools { get; set; } /// /// The server type discriminator. @@ -2232,7 +2261,8 @@ protected SessionConfig(SessionConfig? other) /// When true, assistant.message_delta and assistant.reasoning_delta events /// with deltaContent are sent as the response is generated. /// - public bool Streaming { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? Streaming { get; set; } /// /// Include sub-agent streaming events in the event stream. When true, streaming @@ -2560,7 +2590,8 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// When true, assistant.message_delta and assistant.reasoning_delta events /// with deltaContent are sent as the response is generated. /// - public bool Streaming { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? Streaming { get; set; } /// /// Include sub-agent streaming events in the event stream. When true, streaming @@ -3182,6 +3213,7 @@ public sealed class SystemMessageTransformRpcResponse [JsonSerializable(typeof(SetForegroundSessionResponse))] [JsonSerializable(typeof(SystemMessageConfig))] [JsonSerializable(typeof(ToolBinaryResult))] +[JsonSerializable(typeof(ToolBinaryResultType))] [JsonSerializable(typeof(ToolInvocation))] [JsonSerializable(typeof(ToolResultObject))] [JsonSerializable(typeof(JsonElement))] diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index af17205c0..e27c455dc 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -15,32 +15,6 @@ namespace GitHub.Copilot.SDK.Test.E2E; public class ClientOptionsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "client_options", output) { - [Fact] - public async Task AutoStart_False_Requires_Explicit_Start() - { - await using var client = Ctx.CreateClient(options: new CopilotClientOptions - { - AutoStart = false, - }); - - Assert.Equal(ConnectionState.Disconnected, client.State); - - var ex = await Assert.ThrowsAsync(() => - client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll })); - Assert.Contains("StartAsync", ex.Message, StringComparison.Ordinal); - - await client.StartAsync(); - Assert.Equal(ConnectionState.Connected, client.State); - - var session = await client.CreateSessionAsync(new SessionConfig - { - OnPermissionRequest = PermissionHandler.ApproveAll, - }); - Assert.Matches(@"^[a-f0-9-]+$", session.SessionId); - - await session.DisposeAsync(); - } - [Fact] public async Task Should_Listen_On_Configured_Tcp_Port() { @@ -101,8 +75,7 @@ public async Task Should_Propagate_Process_Options_To_Spawned_Cli() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, CliArgs = ["--capture-file", capturePath], CopilotHome = copilotHomeFromOption, Environment = clientEnv, @@ -165,8 +138,7 @@ public async Task Should_Forward_EnableSessionTelemetry_In_Wire_Request() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, CliArgs = ["--capture-file", capturePath], UseLoggedInUser = false, }); @@ -194,8 +166,7 @@ public async Task Should_Omit_EnableSessionTelemetry_When_Not_Set() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, CliArgs = ["--capture-file", capturePath], UseLoggedInUser = false, }); @@ -222,8 +193,7 @@ public async Task Should_Propagate_Activity_TraceContext_To_Session_Create_And_S await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, CliArgs = ["--capture-file", capturePath], UseLoggedInUser = false, }); @@ -269,8 +239,7 @@ public async Task ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup() useStdio: false, options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, UseLoggedInUser = false, }); @@ -293,8 +262,7 @@ public async Task StartAsync_Cleans_Up_Tcp_Cli_Process_When_Connect_Fails() useStdio: false, options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, CliArgs = ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)], UseLoggedInUser = false, }); @@ -315,8 +283,7 @@ public async Task Should_Propagate_Activity_TraceContext_To_Session_Resume() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - AutoStart = false, - CliPath = cliPath, + CliPath = cliPath, CliArgs = ["--capture-file", capturePath], UseLoggedInUser = false, }); diff --git a/dotnet/test/E2E/ToolsE2ETests.cs b/dotnet/test/E2E/ToolsE2ETests.cs index 529223894..0a3581bbe 100644 --- a/dotnet/test/E2E/ToolsE2ETests.cs +++ b/dotnet/test/E2E/ToolsE2ETests.cs @@ -240,7 +240,7 @@ await session.SendAsync(new MessageOptions BinaryResultsForLlm = [new() { // 2x2 yellow square Data = "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAADklEQVR4nGP4/5/h/38GABkAA/0k+7UAAAAASUVORK5CYII=", - Type = "base64", + Type = ToolBinaryResultType.Image, MimeType = "image/png", }], SessionLog = "Returned an image", diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 57e2d873e..7ff40a489 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -20,9 +20,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() UseStdio = false, CliUrl = "http://localhost:8080", LogLevel = "debug", - AutoStart = false, - - Environment = new Dictionary { ["KEY"] = "value" }, + Environment = new Dictionary { ["KEY"] = "value" }, GitHubToken = "ghp_test", UseLoggedInUser = false, CopilotHome = "/custom/copilot/home", @@ -39,8 +37,6 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() Assert.Equal(original.UseStdio, clone.UseStdio); Assert.Equal(original.CliUrl, clone.CliUrl); Assert.Equal(original.LogLevel, clone.LogLevel); - Assert.Equal(original.AutoStart, clone.AutoStart); - Assert.Equal(original.Environment, clone.Environment); Assert.Equal(original.GitHubToken, clone.GitHubToken); Assert.Equal(original.UseLoggedInUser, clone.UseLoggedInUser); diff --git a/dotnet/test/Unit/PermissionRequestResultKindTests.cs b/dotnet/test/Unit/PermissionRequestResultKindTests.cs index 67c9eeb41..aed32a986 100644 --- a/dotnet/test/Unit/PermissionRequestResultKindTests.cs +++ b/dotnet/test/Unit/PermissionRequestResultKindTests.cs @@ -21,13 +21,6 @@ public void WellKnownKinds_HaveExpectedValues() Assert.Equal("reject", PermissionRequestResultKind.Rejected.Value); Assert.Equal("user-not-available", PermissionRequestResultKind.UserNotAvailable.Value); Assert.Equal("no-result", PermissionRequestResultKind.NoResult.Value); - - // Deprecated aliases still resolve -#pragma warning disable CS0618 - Assert.Equal(PermissionRequestResultKind.Rejected, PermissionRequestResultKind.DeniedInteractivelyByUser); - Assert.Equal(PermissionRequestResultKind.UserNotAvailable, PermissionRequestResultKind.DeniedCouldNotRequestFromUser); - Assert.Equal(PermissionRequestResultKind.UserNotAvailable, PermissionRequestResultKind.DeniedByRules); -#pragma warning restore CS0618 } [Fact] diff --git a/dotnet/test/Unit/SerializationTests.cs b/dotnet/test/Unit/SerializationTests.cs index dc6f4e0c3..6cb1c663f 100644 --- a/dotnet/test/Unit/SerializationTests.cs +++ b/dotnet/test/Unit/SerializationTests.cs @@ -265,7 +265,7 @@ public void McpHttpServerConfig_CanSerializeOauthOptions_WithSdkOptions() Assert.Equal("client-id", httpConfig.OauthClientId); Assert.False(httpConfig.OauthPublicClient); Assert.Equal(McpHttpServerConfigOauthGrantType.ClientCredentials, httpConfig.OauthGrantType); - Assert.Equal("*", Assert.Single(httpConfig.Tools)); + Assert.Equal("*", Assert.Single(httpConfig.Tools!)); Assert.Equal(3000, httpConfig.Timeout); } From b00fd8c9d9d1821036196fdefd8c42fd327dd175 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 14:14:33 +0100 Subject: [PATCH 06/40] Phase 4d/4e: remove CopilotClient.State, retype LogLevel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove CopilotClient.State and the ConnectionState enum (per ApiView decision: 'remove this property') - Remove the _disconnected field that backed State - Convert CopilotClientOptions.LogLevel from bare string with default 'info' to nullable CopilotLogLevel (string-backed struct in the same SDK house style as PermissionRequestResultKind/ToolBinaryResultType) with well-known values: None/Error/Warning/Info/Debug/All (matching the runtime's accepted LOG_LEVELS array). When null, the --log-level arg is omitted, which is equivalent to the runtime's 'default' value. - Don't expose the values as an enum — the runtime doesn't necessarily treat them as a linear scale, so '<'/'>' comparisons would be misleading. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Client.cs | 40 ++---------- dotnet/src/Types.cs | 76 +++++++++++++++++----- dotnet/test/E2E/ClientE2ETests.cs | 7 +- dotnet/test/E2E/ClientLifecycleE2ETests.cs | 7 +- dotnet/test/E2E/ClientOptionsE2ETests.cs | 6 +- dotnet/test/E2E/SessionFsE2ETests.cs | 2 +- dotnet/test/Unit/CloneTests.cs | 2 +- 7 files changed, 71 insertions(+), 69 deletions(-) diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index bb27cf78f..a83934768 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -73,7 +73,6 @@ public sealed partial class CopilotClient : IDisposable, IAsyncDisposable private readonly CopilotClientOptions _options; private readonly ILogger _logger; private Task? _connectionTask; - private volatile bool _disconnected; private bool _disposed; private readonly int? _optionsPort; private readonly string? _optionsHost; @@ -122,7 +121,7 @@ public sealed partial class CopilotClient : IDisposable, IAsyncDisposable /// var client = new CopilotClient(new CopilotClientOptions /// { /// CliPath = "/usr/local/bin/copilot", - /// LogLevel = "debug" + /// LogLevel = CopilotLogLevel.Debug /// }); /// /// @@ -230,7 +229,7 @@ public Task StartAsync(CancellationToken cancellationToken = default) async Task StartCoreAsync(CancellationToken ct) { _logger.LogDebug("Starting Copilot client"); - _disconnected = false; + // Reset disposed flag for restart scenarios var startTimestamp = Stopwatch.GetTimestamp(); Connection? connection = null; @@ -831,32 +830,6 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes return session; } - /// - /// Gets the current connection state of the client. - /// - /// - /// The current : Disconnected, Connecting, Connected, or Error. - /// - /// - /// - /// if (client.State == ConnectionState.Connected) - /// { - /// var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll }); - /// } - /// - /// - public ConnectionState State - { - get - { - if (_connectionTask == null) return ConnectionState.Disconnected; - if (_connectionTask.IsFaulted) return ConnectionState.Error; - if (!_connectionTask.IsCompleted) return ConnectionState.Connecting; - if (_disconnected) return ConnectionState.Disconnected; - return ConnectionState.Connected; - } - } - /// /// Validates the health of the connection by sending a ping request. /// @@ -1421,7 +1394,11 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) args.AddRange(options.CliArgs); } - args.AddRange(["--headless", "--no-auto-update", "--log-level", options.LogLevel]); + args.AddRange(["--headless", "--no-auto-update"]); + if (options.LogLevel is { } logLevel && !string.IsNullOrEmpty(logLevel.Value)) + { + args.AddRange(["--log-level", logLevel.Value]); + } if (options.UseStdio == true) { @@ -1702,9 +1679,6 @@ private async Task ConnectToServerAsync(Process? cliProcess, string? "CopilotClient.ConnectToServerAsync transport setup complete. Elapsed={Elapsed}", setupTimestamp); - // Transition state to Disconnected if the JSON-RPC connection drops - _ = rpc.Completion.ContinueWith(_ => _disconnected = true, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); - _serverRpc = new ServerRpc(rpc); return new Connection(rpc, cliProcess, networkStream, stderrBuffer); diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 5814d4a54..136dc45d5 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -50,23 +50,60 @@ internal static class Diagnostics } /// -/// Represents the connection state of the Copilot client. +/// Log level for the Copilot runtime. Use the well-known values exposed as +/// static members (, , , +/// , , ), or construct +/// your own with if the runtime accepts +/// additional values. The runtime does not necessarily treat the values as a +/// linear scale, so do not assume </> comparisons are meaningful. /// -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum ConnectionState +[DebuggerDisplay("{Value,nq}")] +public readonly struct CopilotLogLevel : IEquatable { - /// The client is not connected to the server. - [JsonStringEnumMemberName("disconnected")] - Disconnected, - /// The client is establishing a connection to the server. - [JsonStringEnumMemberName("connecting")] - Connecting, - /// The client is connected and ready to communicate. - [JsonStringEnumMemberName("connected")] - Connected, - /// The connection is in an error state. - [JsonStringEnumMemberName("error")] - Error + /// Disable logging entirely. + public static CopilotLogLevel None { get; } = new("none"); + + /// Log only errors. + public static CopilotLogLevel Error { get; } = new("error"); + + /// Log warnings and errors. + public static CopilotLogLevel Warning { get; } = new("warning"); + + /// Log informational messages, warnings, and errors. + public static CopilotLogLevel Info { get; } = new("info"); + + /// Log debug-level diagnostics in addition to the above. + public static CopilotLogLevel Debug { get; } = new("debug"); + + /// Log every diagnostic the runtime emits. + public static CopilotLogLevel All { get; } = new("all"); + + /// Gets the underlying string value of this . + public string Value => _value ?? string.Empty; + + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The wire string value for this log level. + public CopilotLogLevel(string value) => _value = value; + + /// + public static bool operator ==(CopilotLogLevel left, CopilotLogLevel right) => left.Equals(right); + + /// + public static bool operator !=(CopilotLogLevel left, CopilotLogLevel right) => !left.Equals(right); + + /// + public override bool Equals([NotNullWhen(true)] object? obj) => obj is CopilotLogLevel other && Equals(other); + + /// + public bool Equals(CopilotLogLevel other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; } /// @@ -143,9 +180,14 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// public string? CliUrl { get; set; } /// - /// Log level for the CLI server (e.g., "info", "debug", "warn", "error"). + /// Log level for the Copilot runtime. Use the well-known values on + /// (, + /// , , + /// , , + /// ). When null, the runtime's default + /// log level is used. /// - public string LogLevel { get; set; } = "info"; + public CopilotLogLevel? LogLevel { get; set; } /// /// Environment variables to pass to the CLI process. /// diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs index b8885fb2d..a64f4d59e 100644 --- a/dotnet/test/E2E/ClientE2ETests.cs +++ b/dotnet/test/E2E/ClientE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -21,14 +21,11 @@ public async Task Should_Start_And_Connect_To_Server(bool useStdio) try { await client.StartAsync(); - Assert.Equal(ConnectionState.Connected, client.State); - var pong = await client.PingAsync("test message"); Assert.Equal("pong: test message", pong.Message); Assert.NotEqual(default, pong.Timestamp); await client.StopAsync(); - Assert.Equal(ConnectionState.Disconnected, client.State); } finally { @@ -45,8 +42,6 @@ public async Task Should_Force_Stop_Without_Cleanup(bool useStdio) await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll }); await client.ForceStopAsync(); - - Assert.Equal(ConnectionState.Disconnected, client.State); } [Theory] diff --git a/dotnet/test/E2E/ClientLifecycleE2ETests.cs b/dotnet/test/E2E/ClientLifecycleE2ETests.cs index 7026093f8..e75cef522 100644 --- a/dotnet/test/E2E/ClientLifecycleE2ETests.cs +++ b/dotnet/test/E2E/ClientLifecycleE2ETests.cs @@ -1,4 +1,4 @@ -/*--------------------------------------------------------------------------------------------- +/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ @@ -66,9 +66,6 @@ public async Task Dispose_Disconnects_Client_And_Disposes_Rpc_Surface(bool useAs { var client = Ctx.CreateClient(); await client.StartAsync(); - - Assert.Equal(ConnectionState.Connected, client.State); - if (useAsyncDispose) { await client.DisposeAsync(); @@ -77,8 +74,6 @@ public async Task Dispose_Disconnects_Client_And_Disposes_Rpc_Surface(bool useAs { client.Dispose(); } - - Assert.Equal(ConnectionState.Disconnected, client.State); Assert.Throws(() => client.Rpc); } diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index e27c455dc..a3a418c50 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -27,8 +27,6 @@ public async Task Should_Listen_On_Configured_Tcp_Port() }); await client.StartAsync(); - - Assert.Equal(ConnectionState.Connected, client.State); Assert.Equal(port, client.ActualPort); var response = await client.PingAsync("fixed-port"); @@ -80,7 +78,7 @@ public async Task Should_Propagate_Process_Options_To_Spawned_Cli() CopilotHome = copilotHomeFromOption, Environment = clientEnv, GitHubToken = "process-option-token", - LogLevel = "debug", + LogLevel = CopilotLogLevel.Debug, SessionIdleTimeoutSeconds = 17, Telemetry = new TelemetryConfig { @@ -247,7 +245,6 @@ public async Task ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup() Assert.Contains("Communication error", ex.Message, StringComparison.Ordinal); await client.ForceStopAsync(); - Assert.Equal(ConnectionState.Disconnected, client.State); } [Fact] @@ -273,7 +270,6 @@ public async Task StartAsync_Cleans_Up_Tcp_Cli_Process_When_Connect_Fails() await AssertProcessExitedAsync(pid); await client.ForceStopAsync(); - Assert.Equal(ConnectionState.Disconnected, client.State); } [Fact] diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index bc974a09d..1d53dfb15 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -111,7 +111,7 @@ public async Task Should_Reject_SetProvider_When_Sessions_Already_Exist() options: new CopilotClientOptions { CliUrl = $"localhost:{port}", - LogLevel = "error", + LogLevel = CopilotLogLevel.Error, SessionFs = SessionFsConfig, TcpConnectionToken = "session-fs-shared-token", }); diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 7ff40a489..3779332d2 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -19,7 +19,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() Port = 8080, UseStdio = false, CliUrl = "http://localhost:8080", - LogLevel = "debug", + LogLevel = CopilotLogLevel.Debug, Environment = new Dictionary { ["KEY"] = "value" }, GitHubToken = "ghp_test", UseLoggedInUser = false, From e400c5cf2511c5f210bfc34f5524abfa3ed3ea96 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 14:36:46 +0100 Subject: [PATCH 07/40] Fix mojibake from cp1252/UTF-8 round-trip in earlier phase commits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A PowerShell editing pipeline in earlier Phase 4 commits read UTF-8 source bytes through a cp1252 decode, corrupting em-dashes (U+2014, UTF-8 E2 80 94) into 'â€\u201d' sequences (UTF-8 C3 A2 E2 82 AC E2 80 9D). Inverse-encoded the affected files via a small fix-mojibake.ps1 utility (in session state) that handles UTF-8 BOMs correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 56 +++++++------- dotnet/src/Client.cs | 2 +- dotnet/src/Session.cs | 24 +++--- dotnet/src/Types.cs | 76 +++++++++---------- dotnet/test/E2E/EventFidelityE2ETests.cs | 2 +- .../MultiClientCommandsElicitationE2ETests.cs | 4 +- .../test/E2E/RpcEventSideEffectsE2ETests.cs | 2 +- dotnet/test/E2E/SessionConfigE2ETests.cs | 8 +- dotnet/test/E2E/SessionE2ETests.cs | 4 +- dotnet/test/E2E/StreamingFidelityE2ETests.cs | 2 +- dotnet/test/Harness/TestHelper.cs | 2 +- 11 files changed, 91 insertions(+), 91 deletions(-) diff --git a/dotnet/README.md b/dotnet/README.md index 1aa444d97..c2d07846b 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -85,7 +85,7 @@ new CopilotClient(CopilotClientOptions? options = null) - `Logger` - `ILogger` instance for SDK logging - `GitHubToken` - GitHub token for authentication. When provided, takes priority over other auth methods. - `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `CliUrl`. -- `Telemetry` - OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. +- `Telemetry` - OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. #### Methods @@ -232,7 +232,7 @@ Get all events/messages from this session. ##### `DisposeAsync(): ValueTask` -Close the session and release in-memory resources. Session data on disk is preserved — the conversation can be resumed later via `ResumeSessionAsync()`. To permanently delete session data, use `client.DeleteSessionAsync()`. +Close the session and release in-memory resources. Session data on disk is preserved — the conversation can be resumed later via `ResumeSessionAsync()`. To permanently delete session data, use `client.DeleteSessionAsync()`. ```csharp // Preferred: automatic cleanup via await using @@ -281,7 +281,7 @@ session.On(evt => The SDK supports image attachments via the `Attachments` parameter. You can attach images by providing their file path, or by passing base64-encoded data directly using a blob attachment: ```csharp -// File attachment — runtime reads from disk +// File attachment — runtime reads from disk await session.SendAsync(new MessageOptions { Prompt = "What's in this image?", @@ -295,7 +295,7 @@ await session.SendAsync(new MessageOptions } }); -// Blob attachment — provide base64 data directly +// Blob attachment — provide base64 data directly await session.SendAsync(new MessageOptions { Prompt = "What's in this image?", @@ -524,7 +524,7 @@ var session = await client.CreateSessionAsync(new SessionConfig Handler = async (context) => { Console.WriteLine($"Deploying with args: {context.Args}"); - // Do work here — any thrown error is reported back to the CLI + // Do work here — any thrown error is reported back to the CLI }, }, ], @@ -537,9 +537,9 @@ Commands are sent to the CLI on both `CreateSessionAsync` and `ResumeSessionAsyn ## UI Elicitation -When the session has elicitation support — either from the CLI's TUI or from another client that registered an `OnElicitationRequest` handler (see [Elicitation Requests](#elicitation-requests)) — the SDK can request interactive form dialogs from the user. The `session.Ui` object provides convenience methods built on a single generic elicitation RPC. +When the session has elicitation support — either from the CLI's TUI or from another client that registered an `OnElicitationRequest` handler (see [Elicitation Requests](#elicitation-requests)) — the SDK can request interactive form dialogs from the user. The `session.Ui` object provides convenience methods built on a single generic elicitation RPC. -> **Capability check:** Elicitation is only available when at least one connected participant advertises support. Always check `session.Capabilities.Ui?.Elicitation` before calling UI methods — this property updates automatically as participants join and leave. +> **Capability check:** Elicitation is only available when at least one connected participant advertises support. Always check `session.Capabilities.Ui?.Elicitation` before calling UI methods — this property updates automatically as participants join and leave. ```csharp var session = await client.CreateSessionAsync(new SessionConfig @@ -550,14 +550,14 @@ var session = await client.CreateSessionAsync(new SessionConfig if (session.Capabilities.Ui?.Elicitation == true) { - // Confirm dialog — returns boolean + // Confirm dialog — returns boolean bool ok = await session.Ui.ConfirmAsync("Deploy to production?"); - // Selection dialog — returns selected value or null + // Selection dialog — returns selected value or null string? env = await session.Ui.SelectAsync("Pick environment", ["production", "staging", "dev"]); - // Text input — returns string or null + // Text input — returns string or null string? name = await session.Ui.InputAsync("Project name:", new UiInputOptions { Title = "Name", @@ -727,7 +727,7 @@ var client = new CopilotClient(new CopilotClientOptions Trace context (`traceparent`/`tracestate`) is automatically propagated between the SDK and CLI on `CreateSessionAsync`, `ResumeSessionAsync`, and `SendAsync` calls, and inbound when the CLI invokes tool handlers. -No extra dependencies — uses built-in `System.Diagnostics.Activity`. +No extra dependencies — uses built-in `System.Diagnostics.Activity`. ## Permission Handling @@ -757,19 +757,19 @@ var session = await client.CreateSessionAsync(new SessionConfig Model = "gpt-5", OnPermissionRequest = async (request, invocation) => { - // request.Kind — string discriminator for the type of operation being requested: - // "shell" — executing a shell command - // "write" — writing or editing a file - // "read" — reading a file - // "mcp" — calling an MCP tool - // "custom_tool" — calling one of your registered tools - // "url" — fetching a URL - // "memory" — accessing or modifying assistant memory - // "hook" — invoking a registered hook - // request.ToolCallId — the tool call that triggered this request - // request.ToolName — name of the tool (for custom-tool / mcp) - // request.FileName — file being written (for write) - // request.FullCommandText — full shell command text (for shell) + // request.Kind — string discriminator for the type of operation being requested: + // "shell" — executing a shell command + // "write" — writing or editing a file + // "read" — reading a file + // "mcp" — calling an MCP tool + // "custom_tool" — calling one of your registered tools + // "url" — fetching a URL + // "memory" — accessing or modifying assistant memory + // "hook" — invoking a registered hook + // request.ToolCallId — the tool call that triggered this request + // request.ToolName — name of the tool (for custom-tool / mcp) + // request.FileName — file being written (for write) + // request.FullCommandText — full shell command text (for shell) if (request.Kind == "shell") { @@ -784,7 +784,7 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Permission Result Kinds -The `Kind` property must be one of the canonical `PermissionRequestResultKind` values. Approval decisions are present-tense — they describe the decision to apply, not the past-tense outcome reported back on `permission.completed` session events. +The `Kind` property must be one of the canonical `PermissionRequestResultKind` values. Approval decisions are present-tense — they describe the decision to apply, not the past-tense outcome reported back on `permission.completed` session events. | Value | Wire value | Meaning | | ------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | @@ -793,7 +793,7 @@ The `Kind` property must be one of the canonical `PermissionRequestResultKind` v | `PermissionRequestResultKind.UserNotAvailable` | `"user-not-available"` | Deny the request because no user is available to confirm it | | `PermissionRequestResultKind.NoResult` | `"no-result"` | Leave the permission request unanswered (the SDK returns without calling the RPC). Not allowed for protocol v2 permission requests (will be rejected). | -> The past-tense names `PermissionRequestResultKind.DeniedInteractivelyByUser`, `PermissionRequestResultKind.DeniedCouldNotRequestFromUser`, and `PermissionRequestResultKind.DeniedByRules` remain as `[Obsolete]` aliases for backward compatibility — prefer the canonical members above in new code. +> The past-tense names `PermissionRequestResultKind.DeniedInteractivelyByUser`, `PermissionRequestResultKind.DeniedCouldNotRequestFromUser`, and `PermissionRequestResultKind.DeniedByRules` remain as `[Obsolete]` aliases for backward compatibility — prefer the canonical members above in new code. ### Resuming Sessions @@ -924,7 +924,7 @@ var session = await client.CreateSessionAsync(new SessionConfig ## Elicitation Requests -Register an `OnElicitationRequest` handler to let your client act as an elicitation provider — presenting form-based UI dialogs on behalf of the agent. When provided, the server notifies your client whenever a tool or MCP server needs structured user input. +Register an `OnElicitationRequest` handler to let your client act as an elicitation provider — presenting form-based UI dialogs on behalf of the agent. When provided, the server notifies your client whenever a tool or MCP server needs structured user input. ```csharp var session = await client.CreateSessionAsync(new SessionConfig @@ -964,7 +964,7 @@ In multi-client scenarios: - If no connected client was previously providing an elicitation capability, but a new client joins that can, all clients will receive a `capabilities.changed` event to notify them that elicitation is now possible. The SDK automatically updates `session.Capabilities` when these events arrive. - Similarly, if the last elicitation provider disconnects, all clients receive a `capabilities.changed` event indicating elicitation is no longer available. -- The server fans out elicitation requests to **all** connected clients that registered a handler — the first response wins. +- The server fans out elicitation requests to **all** connected clients that registered a handler — the first response wins. ## Error Handling diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index a83934768..3b981bc1b 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -1340,7 +1340,7 @@ private async Task VerifyProtocolVersionAsync(Connection connection, Cancellatio catch (IOException ex) when (ex.InnerException is RemoteRpcException remoteEx && IsUnsupportedConnectMethod(remoteEx)) { // Legacy server without `connect`; fall back to `ping`. A token, if any, - // is silently dropped — the legacy server can't enforce one. + // is silently dropped — the legacy server can't enforce one. usedFallbackPing = true; var pingResponse = await InvokeRpcAsync( connection.Rpc, "ping", [new PingRequest()], connection.StderrBuffer, cancellationToken); diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 836d5a174..ade86c718 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -31,7 +31,7 @@ namespace GitHub.Copilot.SDK; /// implements . Use the /// await using pattern for automatic cleanup, or call /// explicitly. Disposing a session releases in-memory resources but preserves session data -/// on disk — the conversation can be resumed later via +/// on disk — the conversation can be resumed later via /// . To permanently delete session data, /// use . /// @@ -421,7 +421,7 @@ internal void DispatchEvent(SessionEvent sessionEvent) { // Fire broadcast work concurrently (fire-and-forget with error logging). // This is done outside the channel so broadcast handlers don't block the - // consumer loop — important when a secondary client's handler intentionally + // consumer loop — important when a secondary client's handler intentionally // never completes (multi-client permission scenario). _ = HandleBroadcastEventAsync(sessionEvent); @@ -710,11 +710,11 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, } catch (IOException) { - // Connection lost or RPC error — nothing we can do + // Connection lost or RPC error — nothing we can do } catch (ObjectDisposedException) { - // Connection already disposed — nothing we can do + // Connection already disposed — nothing we can do } } } @@ -761,11 +761,11 @@ private async Task ExecutePermissionAndRespondAsync(string requestId, Permission } catch (IOException) { - // Connection lost or RPC error — nothing we can do + // Connection lost or RPC error — nothing we can do } catch (ObjectDisposedException) { - // Connection already disposed — nothing we can do + // Connection already disposed — nothing we can do } } } @@ -843,7 +843,7 @@ private async Task ExecuteCommandAndRespondAsync(string requestId, string comman } catch (Exception ex) when (ex is IOException or ObjectDisposedException) { - // Connection lost — nothing we can do + // Connection lost — nothing we can do } return; } @@ -875,7 +875,7 @@ await handler(new CommandContext } catch (Exception error) when (error is not OperationCanceledException) { - // User handler can throw any exception — report the error back to the server + // User handler can throw any exception — report the error back to the server // so the pending command doesn't hang. var message = error.Message; try @@ -884,7 +884,7 @@ await handler(new CommandContext } catch (Exception ex) when (ex is IOException or ObjectDisposedException) { - // Connection lost — nothing we can do + // Connection lost — nothing we can do } } } @@ -923,7 +923,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str } catch (Exception ex) when (ex is not OperationCanceledException) { - // User handler can throw any exception — attempt to cancel so the request doesn't hang. + // User handler can throw any exception — attempt to cancel so the request doesn't hang. try { await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UIElicitationResponse @@ -933,7 +933,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str } catch (Exception innerEx) when (innerEx is IOException or ObjectDisposedException) { - // Connection lost — nothing we can do + // Connection lost — nothing we can do } } } @@ -1451,7 +1451,7 @@ public async Task LogAsync(string message, SessionLogLevel? level = null, bool? /// /// /// - /// // Using 'await using' for automatic disposal — session can still be resumed later + /// // Using 'await using' for automatic disposal — session can still be resumed later /// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll }); /// /// // Or manually dispose diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 136dc45d5..0f4f5825d 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -466,10 +466,10 @@ public sealed class ToolResultObject /// /// Result type indicator. /// - /// "success" — the tool executed successfully. - /// "failure" — the tool encountered an error. - /// "rejected" — the tool invocation was rejected. - /// "denied" — the tool invocation was denied by a permission check. + /// "success" — the tool executed successfully. + /// "failure" — the tool encountered an error. + /// "rejected" — the tool invocation was rejected. + /// "denied" — the tool invocation was denied by a permission check. /// /// [JsonPropertyName("resultType")] @@ -692,10 +692,10 @@ public sealed class PermissionRequestResult /// Permission decision kind. Use the static members of /// to construct values. Valid kinds are: /// - /// "approve-once" () — allow this single request. - /// "reject" () — deny the request. - /// "user-not-available" () — deny because no user is available to confirm. - /// "no-result" () — leave the pending request unanswered (protocol v1 only; rejected by protocol v2 servers). + /// "approve-once" () — allow this single request. + /// "reject" () — deny the request. + /// "user-not-available" () — deny because no user is available to confirm. + /// "no-result" () — leave the pending request unanswered (protocol v1 only; rejected by protocol v2 servers). /// /// [JsonPropertyName("kind")] @@ -947,7 +947,7 @@ public sealed class CommandContext public delegate Task CommandHandler(CommandContext context); // ============================================================================ -// Elicitation Types (UI — client → server) +// Elicitation Types (UI — client → server) // ============================================================================ /// @@ -1078,7 +1078,7 @@ public interface ISessionUiApi } // ============================================================================ -// Elicitation Types (server → client callback) +// Elicitation Types (server → client callback) // ============================================================================ /// @@ -1196,9 +1196,9 @@ public sealed class PreToolUseHookOutput /// /// Permission decision for the pending tool call. /// - /// "allow" — permit the tool to execute. - /// "deny" — block the tool from executing. - /// "ask" — fall through to the normal permission prompt. + /// "allow" — permit the tool to execute. + /// "deny" — block the tool from executing. + /// "ask" — fall through to the normal permission prompt. /// /// [JsonPropertyName("permissionDecision")] @@ -1390,9 +1390,9 @@ public sealed class SessionStartHookInput /// /// Source of the session start. /// - /// "startup" — initial application startup. - /// "resume" — resuming a previous session. - /// "new" — starting a brand new session. + /// "startup" — initial application startup. + /// "resume" — resuming a previous session. + /// "new" — starting a brand new session. /// /// [JsonPropertyName("source")] @@ -1454,11 +1454,11 @@ public sealed class SessionEndHookInput /// /// Reason for session end. /// - /// "complete" — the session finished normally. - /// "error" — the session ended due to an error. - /// "abort" — the session was aborted. - /// "timeout" — the session timed out. - /// "user_exit" — the user exited the session. + /// "complete" — the session finished normally. + /// "error" — the session ended due to an error. + /// "abort" — the session was aborted. + /// "timeout" — the session timed out. + /// "user_exit" — the user exited the session. /// /// [JsonPropertyName("reason")] @@ -1538,10 +1538,10 @@ public sealed class ErrorOccurredHookInput /// /// Context of the error. /// - /// "model_call" — error during a model API call. - /// "tool_execution" — error during tool execution. - /// "system" — internal system error. - /// "user_input" — error processing user input. + /// "model_call" — error during a model API call. + /// "tool_execution" — error during tool execution. + /// "system" — internal system error. + /// "user_input" — error processing user input. /// /// [JsonPropertyName("errorContext")] @@ -1568,9 +1568,9 @@ public sealed class ErrorOccurredHookOutput /// /// Error handling strategy. /// - /// "retry" — retry the failed operation. - /// "skip" — skip the failed operation and continue. - /// "abort" — abort the session. + /// "retry" — retry the failed operation. + /// "skip" — skip the failed operation and continue. + /// "abort" — abort the session. /// /// [JsonPropertyName("errorHandling")] @@ -1690,7 +1690,7 @@ public sealed class SectionOverride /// /// Transform callback. When set, takes precedence over Action. /// Receives current section content, returns transformed content. - /// Not serialized — the SDK handles this locally. + /// Not serialized — the SDK handles this locally. /// [JsonIgnore] public Func>? Transform { get; set; } @@ -2390,9 +2390,9 @@ protected SessionConfig(SessionConfig? other) /// /// Per-session remote behavior control: /// - /// "off" — local only, no remote export (default) - /// "export" — export session events to GitHub without enabling remote steering - /// "on" — export to GitHub AND enable remote steering + /// "off" — local only, no remote export (default) + /// "export" — export session events to GitHub without enabling remote steering + /// "on" — export to GitHub AND enable remote steering /// /// public RemoteSessionMode? RemoteSession { get; set; } @@ -2903,12 +2903,12 @@ public sealed class GetAuthStatusResponse /// /// Authentication type. /// - /// "user" — authenticated via user login. - /// "env" — authenticated via environment variable. - /// "gh-cli" — authenticated via the GitHub CLI. - /// "hmac" — authenticated via HMAC signature. - /// "api-key" — authenticated via API key. - /// "token" — authenticated via explicit token. + /// "user" — authenticated via user login. + /// "env" — authenticated via environment variable. + /// "gh-cli" — authenticated via the GitHub CLI. + /// "hmac" — authenticated via HMAC signature. + /// "api-key" — authenticated via API key. + /// "token" — authenticated via explicit token. /// /// [JsonPropertyName("authType")] diff --git a/dotnet/test/E2E/EventFidelityE2ETests.cs b/dotnet/test/E2E/EventFidelityE2ETests.cs index fee851c8e..ae925cc80 100644 --- a/dotnet/test/E2E/EventFidelityE2ETests.cs +++ b/dotnet/test/E2E/EventFidelityE2ETests.cs @@ -229,7 +229,7 @@ await session.SendAndWaitAsync(new MessageOptions var types = messages.Select(m => m.Type).ToList(); // Verify complete event ordering contract: - // session.start → user.message → tool.execution_start → tool.execution_complete → assistant.message + // session.start → user.message → tool.execution_start → tool.execution_complete → assistant.message var sessionStartIdx = types.IndexOf("session.start"); var userMsgIdx = types.IndexOf("user.message"); var toolStartIdx = types.IndexOf("tool.execution_start"); diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index 2a41b5d1e..115565816 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -168,7 +168,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici } }); - // Client2 joins WITH elicitation handler — triggers capabilities.changed + // Client2 joins WITH elicitation handler — triggers capabilities.changed var session2 = await Client2.ResumeSessionAsync(session1.SessionId, new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, @@ -250,7 +250,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec } }); - // Force-stop client3 — destroys the socket, triggering server-side cleanup + // Force-stop client3 — destroys the socket, triggering server-side cleanup await _client3.ForceStopAsync(); _client3 = null; diff --git a/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs b/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs index ef18be921..87336728c 100644 --- a/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs +++ b/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs @@ -30,7 +30,7 @@ public async Task Should_Emit_Mode_Changed_Event_When_Mode_Set() session, evt => evt.Data.NewMode == SessionMode.Plan && evt.Data.PreviousMode == SessionMode.Interactive, EventTimeout, - timeoutDescription: "session.mode_changed event for interactive→plan"); + timeoutDescription: "session.mode_changed event for interactive→plan"); await session.Rpc.Mode.SetAsync(SessionMode.Plan); diff --git a/dotnet/test/E2E/SessionConfigE2ETests.cs b/dotnet/test/E2E/SessionConfigE2ETests.cs index d269fd092..c03315459 100644 --- a/dotnet/test/E2E/SessionConfigE2ETests.cs +++ b/dotnet/test/E2E/SessionConfigE2ETests.cs @@ -34,7 +34,7 @@ public async Task Vision_Disabled_Then_Enabled_Via_SetModel() }, }); - // Turn 1: vision off — no image_url expected + // Turn 1: vision off — no image_url expected await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT1 = await Ctx.GetExchangesAsync(); var t1Messages = trafficAfterT1.SelectMany(e => e.Request.Messages).ToList(); @@ -49,7 +49,7 @@ await session.SetModelAsync( Supports = new ModelCapabilitiesOverrideSupports { Vision = true }, }); - // Turn 2: vision on — image_url expected + // Turn 2: vision on — image_url expected await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT2 = await Ctx.GetExchangesAsync(); var newExchanges = trafficAfterT2.Skip(trafficAfterT1.Count).ToList(); @@ -74,7 +74,7 @@ public async Task Vision_Enabled_Then_Disabled_Via_SetModel() }, }); - // Turn 1: vision on — image_url expected + // Turn 1: vision on — image_url expected await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT1 = await Ctx.GetExchangesAsync(); var t1Messages = trafficAfterT1.SelectMany(e => e.Request.Messages).ToList(); @@ -89,7 +89,7 @@ await session.SetModelAsync( Supports = new ModelCapabilitiesOverrideSupports { Vision = false }, }); - // Turn 2: vision off — no image_url expected in new exchanges + // Turn 2: vision off — no image_url expected in new exchanges await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt }); var trafficAfterT2 = await Ctx.GetExchangesAsync(); var newExchanges = trafficAfterT2.Skip(trafficAfterT1.Count).ToList(); diff --git a/dotnet/test/E2E/SessionE2ETests.cs b/dotnet/test/E2E/SessionE2ETests.cs index 7c57a3ad8..339f3b013 100644 --- a/dotnet/test/E2E/SessionE2ETests.cs +++ b/dotnet/test/E2E/SessionE2ETests.cs @@ -371,7 +371,7 @@ public async Task Should_Receive_Session_Events() Assert.Contains(observedEvents, evt => evt is AssistantMessageEvent); Assert.Contains(observedEvents, evt => evt is SessionIdleEvent); - // Events must be dispatched serially — never more than one handler invocation at a time. + // Events must be dispatched serially — never more than one handler invocation at a time. Assert.Equal(1, maxConcurrent); // Verify the assistant response contains the expected answer. @@ -670,7 +670,7 @@ public async Task DisposeAsync_From_Handler_Does_Not_Deadlock() { if (evt is UserMessageEvent) { - // Call DisposeAsync from within a handler — must not deadlock. + // Call DisposeAsync from within a handler — must not deadlock. session.DisposeAsync().AsTask().ContinueWith(_ => disposed.TrySetResult()); } }); diff --git a/dotnet/test/E2E/StreamingFidelityE2ETests.cs b/dotnet/test/E2E/StreamingFidelityE2ETests.cs index 7f7847b99..6c6de81d8 100644 --- a/dotnet/test/E2E/StreamingFidelityE2ETests.cs +++ b/dotnet/test/E2E/StreamingFidelityE2ETests.cs @@ -142,7 +142,7 @@ public async Task Should_Not_Produce_Deltas_After_Session_Resume_With_Streaming_ public async Task Should_Emit_Streaming_Deltas_With_Reasoning_Effort_Configured() { // Verifies that setting ReasoningEffort alongside Streaming=true does not break - // the streaming pipeline — deltas still arrive and complete successfully. + // the streaming pipeline — deltas still arrive and complete successfully. var session = await CreateSessionAsync(new SessionConfig { Streaming = true, diff --git a/dotnet/test/Harness/TestHelper.cs b/dotnet/test/Harness/TestHelper.cs index ee3e4b159..f8b6114e9 100644 --- a/dotnet/test/Harness/TestHelper.cs +++ b/dotnet/test/Harness/TestHelper.cs @@ -21,7 +21,7 @@ public static class TestHelper var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var cts = new CancellationTokenSource(timeout ?? DefaultEventTimeout); - // Both `finalAssistantMessage` and `sawIdle` are set from two threads — the + // Both `finalAssistantMessage` and `sawIdle` are set from two threads — the // subscription callback (CLI read loop) and CheckExistingMessages (RPC reply). // We complete only once we've observed both, regardless of which path saw which. var stateLock = new object(); From ff5d96bbac9de7f014d482f03a81ec4d5328f7e6 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 14:45:51 +0100 Subject: [PATCH 08/40] Phase 4f: generic OnLifecycle + On, polymorphic lifecycle events - Add SessionCreatedEvent / SessionDeletedEvent / SessionUpdatedEvent / SessionForegroundEvent / SessionBackgroundEvent as sealed derived types of SessionLifecycleEvent. Unknown future event types deserialize to the base SessionLifecycleEvent for forward compatibility (consumers can still inspect Type). - Remove the SessionLifecycleEventTypes static constants class (subsumed by the typed hierarchy). - Replace CopilotClient.On / CopilotClient.On(string, ...) with a single generic OnLifecycle(Action) where T : SessionLifecycleEvent. Consumers pass a derived type to filter, or SessionLifecycleEvent to receive all. - Replace CopilotSession.On(SessionEventHandler) with generic On(Action) where T : SessionEvent. Same filtering pattern. - Remove the SessionEventHandler delegate; SessionConfig.OnEvent / ResumeSessionConfig.OnEvent are now Action?. - Update samples, tests, and README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 14 +-- dotnet/samples/Chat.cs | 2 +- dotnet/samples/ManualToolResume.cs | 2 +- dotnet/src/Client.cs | 115 ++++++------------ dotnet/src/Session.cs | 32 +++-- dotnet/src/Types.cs | 55 +++++---- dotnet/test/E2E/AbortE2ETests.cs | 6 +- dotnet/test/E2E/ClientLifecycleE2ETests.cs | 22 ++-- dotnet/test/E2E/CompactionE2ETests.cs | 2 +- dotnet/test/E2E/EventFidelityE2ETests.cs | 12 +- dotnet/test/E2E/ModeHandlersE2ETests.cs | 2 +- .../MultiClientCommandsElicitationE2ETests.cs | 8 +- dotnet/test/E2E/MultiClientE2ETests.cs | 12 +- dotnet/test/E2E/MultiTurnE2ETests.cs | 4 +- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 2 +- dotnet/test/E2E/PermissionE2ETests.cs | 12 +- dotnet/test/E2E/SessionE2ETests.cs | 12 +- dotnet/test/E2E/SessionFsE2ETests.cs | 2 +- dotnet/test/E2E/SessionFsSqliteE2ETests.cs | 2 +- dotnet/test/E2E/SessionLifecycleE2ETests.cs | 4 +- dotnet/test/E2E/StreamingFidelityE2ETests.cs | 12 +- dotnet/test/E2E/SuspendE2ETests.cs | 2 +- dotnet/test/E2E/ToolResultsE2ETests.cs | 4 +- dotnet/test/Harness/TestHelper.cs | 4 +- 24 files changed, 160 insertions(+), 184 deletions(-) diff --git a/dotnet/README.md b/dotnet/README.md index c2d07846b..42ea340c1 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -43,7 +43,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig // Wait for the response using the session.idle event var done = new TaskCompletionSource(); -session.On(evt => +session.On(evt => { if (evt is AssistantMessageEvent msg) { @@ -158,7 +158,7 @@ Request the TUI to switch to displaying the specified session. Only available in Subscribe to all session lifecycle events. Returns an `IDisposable` that unsubscribes when disposed. ```csharp -using var subscription = client.On(evt => +using var subscription = client.OnLifecycle(evt => { Console.WriteLine($"Session {evt.SessionId}: {evt.Type}"); }); @@ -169,7 +169,7 @@ using var subscription = client.On(evt => Subscribe to a specific lifecycle event type. Use `SessionLifecycleEventTypes` constants. ```csharp -using var subscription = client.On(SessionLifecycleEventTypes.Foreground, evt => +using var subscription = client.OnLifecycle(evt => { Console.WriteLine($"Session {evt.SessionId} is now in foreground"); }); @@ -208,12 +208,12 @@ Send a message to the session. Returns the message ID. -##### `On(SessionEventHandler handler): IDisposable` +##### `On(Action handler): IDisposable` Subscribe to session events. Returns a disposable to unsubscribe. ```csharp -var subscription = session.On(evt => +var subscription = session.On(evt => { Console.WriteLine($"Event: {evt.Type}"); }); @@ -262,7 +262,7 @@ Sessions emit various events during processing. Each event type is a class that Use pattern matching to handle specific event types: ```csharp -session.On(evt => +session.On(evt => { switch (evt) { @@ -330,7 +330,7 @@ var session = await client.CreateSessionAsync(new SessionConfig // Use TaskCompletionSource to wait for completion var done = new TaskCompletionSource(); -session.On(evt => +session.On(evt => { switch (evt) { diff --git a/dotnet/samples/Chat.cs b/dotnet/samples/Chat.cs index 6345dd05c..9e1be66c7 100644 --- a/dotnet/samples/Chat.cs +++ b/dotnet/samples/Chat.cs @@ -8,7 +8,7 @@ OnPermissionRequest = PermissionHandler.ApproveAll }); -using var _ = session.On(evt => +using var _ = session.On(evt => { Console.ForegroundColor = ConsoleColor.Blue; switch (evt) diff --git a/dotnet/samples/ManualToolResume.cs b/dotnet/samples/ManualToolResume.cs index 7658dde11..07d310024 100644 --- a/dotnet/samples/ManualToolResume.cs +++ b/dotnet/samples/ManualToolResume.cs @@ -80,7 +80,7 @@ static async Task WaitForEventAsync(CopilotSession session, Func? { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); IDisposable? subscription = null; - subscription = session.On(evt => + subscription = session.On(evt => { if (evt is T typed && (predicate?.Invoke(typed) ?? true)) { diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 3b981bc1b..081ac0ccb 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -41,7 +41,7 @@ namespace GitHub.Copilot.SDK; /// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll, Model = "gpt-4" }); /// /// // Handle events -/// using var subscription = session.On(evt => +/// using var subscription = session.On<SessionEvent>(evt => /// { /// if (evt is AssistantMessageEvent assistantMessage) /// Console.WriteLine(assistantMessage.Data?.Content); @@ -82,11 +82,12 @@ public sealed partial class CopilotClient : IDisposable, IAsyncDisposable private List? _modelsCache; private readonly SemaphoreSlim _modelsCacheLock = new(1, 1); private readonly Func>>? _onListModels; - private readonly List> _lifecycleHandlers = []; - private readonly Dictionary>> _typedLifecycleHandlers = []; + private readonly List _lifecycleHandlers = []; private readonly object _lifecycleHandlersLock = new(); private ServerRpc? _serverRpc; + private sealed record LifecycleSubscription(Type EventType, Action Handler); + /// /// Gets the typed RPC client for server-scoped methods (no session required). /// @@ -584,7 +585,7 @@ public async Task CreateSessionAsync(SessionConfig config, Cance } if (config.OnEvent != null) { - session.On(config.OnEvent); + session.On(config.OnEvent); } ConfigureSessionFsHandlers(session, config.CreateSessionFsProvider); RegisterSession(session); @@ -742,7 +743,7 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes } if (config.OnEvent != null) { - session.On(config.OnEvent); + session.On(config.OnEvent); } ConfigureSessionFsHandlers(session, config.CreateSessionFsProvider); RegisterSession(session); @@ -1102,103 +1103,59 @@ public async Task SetForegroundSessionIdAsync(string sessionId, CancellationToke } /// - /// Subscribes to all session lifecycle events. - /// - /// - /// Lifecycle events are emitted when sessions are created, deleted, updated, - /// or change foreground/background state (in TUI+server mode). - /// - /// A callback function that receives lifecycle events. - /// An IDisposable that, when disposed, unsubscribes the handler. - /// - /// - /// using var subscription = client.On(evt => - /// { - /// Console.WriteLine($"Session {evt.SessionId}: {evt.Type}"); - /// }); - /// - /// - public IDisposable On(Action handler) - { - ArgumentNullException.ThrowIfNull(handler); - - lock (_lifecycleHandlersLock) - { - _lifecycleHandlers.Add(handler); - } - - return new ActionDisposable(() => - { - lock (_lifecycleHandlersLock) - { - _lifecycleHandlers.Remove(handler); - } - }); - } - - /// - /// Subscribes to a specific session lifecycle event type. + /// Subscribes to session lifecycle events of a specific kind. /// - /// The event type to listen for (use SessionLifecycleEventTypes constants). - /// A callback function that receives events of the specified type. - /// An IDisposable that, when disposed, unsubscribes the handler. + /// + /// The lifecycle event type to listen for. Pass a derived type such as + /// to filter by kind, or + /// to receive every lifecycle event. + /// + /// A callback invoked when a matching lifecycle event arrives. + /// An that, when disposed, unsubscribes the handler. /// /// - /// using var subscription = client.On(SessionLifecycleEventTypes.Foreground, evt => + /// using var sub = client.OnLifecycle<SessionForegroundEvent>(evt => /// { /// Console.WriteLine($"Session {evt.SessionId} is now in foreground"); /// }); /// /// - public IDisposable On(string eventType, Action handler) + public IDisposable OnLifecycle(Action handler) where T : SessionLifecycleEvent { - ArgumentNullException.ThrowIfNull(eventType); ArgumentNullException.ThrowIfNull(handler); + var subscription = new LifecycleSubscription(typeof(T), evt => handler((T)evt)); + lock (_lifecycleHandlersLock) { - if (!_typedLifecycleHandlers.TryGetValue(eventType, out var handlers)) - { - handlers = []; - _typedLifecycleHandlers[eventType] = handlers; - } - - handlers.Add(handler); + _lifecycleHandlers.Add(subscription); } return new ActionDisposable(() => { lock (_lifecycleHandlersLock) { - if (_typedLifecycleHandlers.TryGetValue(eventType, out var handlers)) - { - handlers.Remove(handler); - } + _lifecycleHandlers.Remove(subscription); } }); } private void DispatchLifecycleEvent(SessionLifecycleEvent evt) { - List> typedHandlers; - List> wildcardHandlers; - + List snapshot; lock (_lifecycleHandlersLock) { - typedHandlers = _typedLifecycleHandlers.TryGetValue(evt.Type, out var handlers) - ? [.. handlers] - : []; - wildcardHandlers = [.. _lifecycleHandlers]; + snapshot = [.. _lifecycleHandlers]; } - foreach (var handler in typedHandlers) + var eventType = evt.GetType(); + foreach (var subscription in snapshot) { - try { handler(evt); } catch { /* Ignore handler errors */ } - } - - foreach (var handler in wildcardHandlers) - { - try { handler(evt); } catch { /* Ignore handler errors */ } + if (!subscription.EventType.IsAssignableFrom(eventType)) + { + continue; + } + try { subscription.Handler(evt); } catch { /* Ignore handler errors */ } } } @@ -1766,13 +1723,19 @@ public void OnSessionEvent(string sessionId, JsonElement? @event) public void OnSessionLifecycle(string type, string sessionId, JsonElement? metadata) { - var evt = new SessionLifecycleEvent + SessionLifecycleEvent evt = type switch { - Type = type, - SessionId = sessionId + "session.created" => new SessionCreatedEvent(), + "session.deleted" => new SessionDeletedEvent(), + "session.updated" => new SessionUpdatedEvent(), + "session.foreground" => new SessionForegroundEvent(), + "session.background" => new SessionBackgroundEvent(), + _ => new SessionLifecycleEvent() }; - if (metadata != null) + evt.Type = type; + evt.SessionId = sessionId; + if (metadata is not null) { evt.Metadata = JsonSerializer.Deserialize( metadata.Value.GetRawText(), diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index ade86c718..74b9af946 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -41,7 +41,7 @@ namespace GitHub.Copilot.SDK; /// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll, Model = "gpt-4" }); /// /// // Subscribe to events -/// using var subscription = session.On(evt => +/// using var subscription = session.On<SessionEvent>(evt => /// { /// if (evt is AssistantMessageEvent assistantMessage) /// { @@ -65,7 +65,9 @@ public sealed partial class CopilotSession : IAsyncDisposable private volatile ElicitationHandler? _elicitationHandler; private volatile ExitPlanModeHandler? _exitPlanModeHandler; private volatile AutoModeSwitchHandler? _autoModeSwitchHandler; - private ImmutableArray _eventHandlers = ImmutableArray.Empty; + private ImmutableArray _eventHandlers = ImmutableArray.Empty; + + private sealed record EventSubscription(Type EventType, Action Handler); private SessionHooks? _hooks; private readonly SemaphoreSlim _hooksLock = new(1, 1); @@ -318,7 +320,7 @@ void Handler(SessionEvent evt) } } - using var subscription = On(Handler); + using var subscription = On(Handler); await SendAsync(options, cancellationToken); @@ -381,7 +383,7 @@ void Handler(SessionEvent evt) /// /// /// - /// using var subscription = session.On(evt => + /// using var subscription = session.On<SessionEvent>(evt => /// { /// switch (evt) /// { @@ -394,16 +396,21 @@ void Handler(SessionEvent evt) /// } /// }); /// + /// // Or filter to a specific event kind at compile time: + /// using var sub2 = session.On<AssistantMessageEvent>(evt => + /// Console.WriteLine(evt.Data?.Content)); + /// /// // The handler is automatically unsubscribed when the subscription is disposed. /// /// - public IDisposable On(SessionEventHandler handler) + public IDisposable On(Action handler) where T : SessionEvent { ArgumentNullException.ThrowIfNull(handler); ThrowIfDisposed(); - ImmutableInterlocked.Update(ref _eventHandlers, array => array.Add(handler)); - return new ActionDisposable(() => ImmutableInterlocked.Update(ref _eventHandlers, array => array.Remove(handler))); + var subscription = new EventSubscription(typeof(T), evt => handler((T)evt)); + ImmutableInterlocked.Update(ref _eventHandlers, array => array.Add(subscription)); + return new ActionDisposable(() => ImmutableInterlocked.Update(ref _eventHandlers, array => array.Remove(subscription))); } /// @@ -438,11 +445,16 @@ private async Task ProcessEventsAsync() await foreach (var sessionEvent in _eventChannel.Reader.ReadAllAsync()) { var dispatchTimestamp = Stopwatch.GetTimestamp(); - foreach (var handler in _eventHandlers) + var eventType = sessionEvent.GetType(); + foreach (var subscription in _eventHandlers) { + if (!subscription.EventType.IsAssignableFrom(eventType)) + { + continue; + } try { - handler(sessionEvent); + subscription.Handler(sessionEvent); } catch (Exception ex) { @@ -1488,7 +1500,7 @@ await InvokeRpcAsync( GC.SuppressFinalize(this); } - _eventHandlers = ImmutableInterlocked.InterlockedExchange(ref _eventHandlers, ImmutableArray.Empty); + _eventHandlers = ImmutableInterlocked.InterlockedExchange(ref _eventHandlers, ImmutableArray.Empty); _toolHandlers.Clear(); _commandHandlers.Clear(); diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 0f4f5825d..e8d4dfcfc 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -2372,7 +2372,7 @@ protected SessionConfig(SessionConfig? other) /// Using this property rather than guarantees that early events emitted /// by the CLI during session creation (e.g. session.start) are delivered to the handler. /// - public SessionEventHandler? OnEvent { get; set; } + public Action? OnEvent { get; set; } /// /// Supplies a handler for session filesystem operations. @@ -2694,7 +2694,7 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// Optional event handler registered before the session.resume RPC is issued, /// ensuring early events are delivered. See . /// - public SessionEventHandler? OnEvent { get; set; } + public Action? OnEvent { get; set; } /// /// Supplies a handler for session filesystem operations. @@ -2789,11 +2789,6 @@ public virtual MessageOptions Clone() } } -/// -/// Delegate for handling session events emitted during a Copilot session. -/// -public delegate void SessionEventHandler(SessionEvent sessionEvent); - /// /// Working directory context for a session. /// @@ -3092,24 +3087,7 @@ public sealed class GetModelsResponse // ============================================================================ /// -/// Types of session lifecycle events -/// -public static class SessionLifecycleEventTypes -{ - /// A new session was created. - public const string Created = "session.created"; - /// A session was deleted. - public const string Deleted = "session.deleted"; - /// A session was updated. - public const string Updated = "session.updated"; - /// A session was brought to the foreground. - public const string Foreground = "session.foreground"; - /// A session was moved to the background. - public const string Background = "session.background"; -} - -/// -/// Metadata for session lifecycle events +/// Metadata for session lifecycle events. /// public sealed class SessionLifecycleEventMetadata { @@ -3133,12 +3111,20 @@ public sealed class SessionLifecycleEventMetadata } /// -/// Session lifecycle event notification +/// Session lifecycle event notification. Use derived types +/// (, , +/// , , +/// ) for known kinds. The base type is +/// instantiated when the runtime emits an event kind not known to this SDK +/// version, so consumers can still inspect for forward +/// compatibility. /// public class SessionLifecycleEvent { /// - /// Type of lifecycle event (see ). + /// Wire-format type discriminator (e.g., "session.created"). Useful + /// when the runtime emits an event kind not yet known to this SDK; for + /// known kinds, prefer pattern-matching on the derived type instead. /// [JsonPropertyName("type")] public string Type { get; set; } = string.Empty; @@ -3156,6 +3142,21 @@ public class SessionLifecycleEvent public SessionLifecycleEventMetadata? Metadata { get; set; } } +/// Raised when a new session is created. +public sealed class SessionCreatedEvent : SessionLifecycleEvent { } + +/// Raised when a session is deleted. +public sealed class SessionDeletedEvent : SessionLifecycleEvent { } + +/// Raised when a session's metadata is updated. +public sealed class SessionUpdatedEvent : SessionLifecycleEvent { } + +/// Raised when a session is brought to the foreground (TUI+server mode). +public sealed class SessionForegroundEvent : SessionLifecycleEvent { } + +/// Raised when a session moves to the background (TUI+server mode). +public sealed class SessionBackgroundEvent : SessionLifecycleEvent { } + /// /// Response from session.getForeground /// diff --git a/dotnet/test/E2E/AbortE2ETests.cs b/dotnet/test/E2E/AbortE2ETests.cs index 009ca1e29..fa8af0480 100644 --- a/dotnet/test/E2E/AbortE2ETests.cs +++ b/dotnet/test/E2E/AbortE2ETests.cs @@ -25,7 +25,7 @@ public async Task Should_Abort_During_Active_Streaming() var firstDeltaReceived = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var allEvents = new List(); - session.On(evt => + session.On(evt => { lock (allEvents) { allEvents.Add(evt); } if (evt is AssistantMessageDeltaEvent delta) @@ -60,7 +60,7 @@ public async Task Should_Abort_During_Active_Streaming() // recovery message rather than racing against a late idle from the // aborted streaming turn. var recoveryReceived = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - session.On(evt => + session.On(evt => { if (evt is AssistantMessageEvent msg && (msg.Data.Content?.Contains("abort_recovery_ok") == true)) { @@ -109,7 +109,7 @@ public async Task Should_Abort_During_Active_Tool_Execution() // Session should be usable after abort — verify by listening for the right event var recoveryReceived = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - session.On(evt => + session.On(evt => { if (evt is AssistantMessageEvent msg && (msg.Data.Content?.Contains("tool_abort_recovery_ok") == true)) { diff --git a/dotnet/test/E2E/ClientLifecycleE2ETests.cs b/dotnet/test/E2E/ClientLifecycleE2ETests.cs index e75cef522..e0179cfbb 100644 --- a/dotnet/test/E2E/ClientLifecycleE2ETests.cs +++ b/dotnet/test/E2E/ClientLifecycleE2ETests.cs @@ -15,9 +15,9 @@ public class ClientLifecycleE2ETests(E2ETestFixture fixture, ITestOutputHelper o public async Task Should_Receive_Session_Created_Lifecycle_Event() { var created = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using var subscription = Client.On(evt => + using var subscription = Client.OnLifecycle(evt => { - if (evt.Type == SessionLifecycleEventTypes.Created) + if (evt is SessionCreatedEvent) { created.TrySetResult(evt); } @@ -26,7 +26,7 @@ public async Task Should_Receive_Session_Created_Lifecycle_Event() await using var session = await CreateSessionAsync(); var evt = await created.Task.WaitAsync(TimeSpan.FromSeconds(10)); - Assert.Equal(SessionLifecycleEventTypes.Created, evt.Type); + Assert.IsType(evt); Assert.Equal(session.SessionId, evt.SessionId); } @@ -34,12 +34,12 @@ public async Task Should_Receive_Session_Created_Lifecycle_Event() public async Task Should_Filter_Session_Lifecycle_Events_By_Type() { var created = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using var subscription = Client.On(SessionLifecycleEventTypes.Created, evt => created.TrySetResult(evt)); + using var subscription = Client.OnLifecycle(evt => created.TrySetResult(evt)); await using var session = await CreateSessionAsync(); var evt = await created.Task.WaitAsync(TimeSpan.FromSeconds(10)); - Assert.Equal(SessionLifecycleEventTypes.Created, evt.Type); + Assert.IsType(evt); Assert.Equal(session.SessionId, evt.SessionId); } @@ -48,9 +48,9 @@ public async Task Disposing_Lifecycle_Subscription_Stops_Receiving_Events() { var count = 0; var created = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var subscription = Client.On(_ => Interlocked.Increment(ref count)); + var subscription = Client.OnLifecycle(_ => Interlocked.Increment(ref count)); subscription.Dispose(); - using var activeSubscription = Client.On(SessionLifecycleEventTypes.Created, evt => created.TrySetResult(evt)); + using var activeSubscription = Client.OnLifecycle(evt => created.TrySetResult(evt)); await using var session = await CreateSessionAsync(); var evt = await created.Task.WaitAsync(TimeSpan.FromSeconds(10)); @@ -83,7 +83,7 @@ public async Task Should_Receive_Session_Updated_Lifecycle_Event_For_Non_Ephemer await using var session = await CreateSessionAsync(); var updated = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using var subscription = Client.On(SessionLifecycleEventTypes.Updated, evt => + using var subscription = Client.OnLifecycle(evt => { if (string.Equals(evt.SessionId, session.SessionId, StringComparison.Ordinal)) { @@ -96,7 +96,7 @@ public async Task Should_Receive_Session_Updated_Lifecycle_Event_For_Non_Ephemer await session.Rpc.Mode.SetAsync(SessionMode.Plan); var evt = await updated.Task.WaitAsync(TimeSpan.FromSeconds(15)); - Assert.Equal(SessionLifecycleEventTypes.Updated, evt.Type); + Assert.IsType(evt); Assert.Equal(session.SessionId, evt.SessionId); } @@ -113,7 +113,7 @@ public async Task Should_Receive_Session_Deleted_Lifecycle_Event_When_Deleted() await session.SendAndWaitAsync(new MessageOptions { Prompt = "Say SESSION_DELETED_OK exactly." }); var deleted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using var subscription = Client.On(SessionLifecycleEventTypes.Deleted, evt => + using var subscription = Client.OnLifecycle(evt => { if (string.Equals(evt.SessionId, sessionId, StringComparison.Ordinal)) { @@ -127,7 +127,7 @@ public async Task Should_Receive_Session_Deleted_Lifecycle_Event_When_Deleted() await Client.DeleteSessionAsync(sessionId); var evt = await deleted.Task.WaitAsync(TimeSpan.FromSeconds(15)); - Assert.Equal(SessionLifecycleEventTypes.Deleted, evt.Type); + Assert.IsType(evt); Assert.Equal(sessionId, evt.SessionId); await session.DisposeAsync(); diff --git a/dotnet/test/E2E/CompactionE2ETests.cs b/dotnet/test/E2E/CompactionE2ETests.cs index abee92219..70f1ff900 100644 --- a/dotnet/test/E2E/CompactionE2ETests.cs +++ b/dotnet/test/E2E/CompactionE2ETests.cs @@ -85,7 +85,7 @@ public async Task Should_Not_Emit_Compaction_Events_When_Infinite_Sessions_Disab var compactionEvents = new List(); - session.On(evt => + session.On(evt => { if (evt is SessionCompactionStartEvent or SessionCompactionCompleteEvent) { diff --git a/dotnet/test/E2E/EventFidelityE2ETests.cs b/dotnet/test/E2E/EventFidelityE2ETests.cs index ae925cc80..fd2578b92 100644 --- a/dotnet/test/E2E/EventFidelityE2ETests.cs +++ b/dotnet/test/E2E/EventFidelityE2ETests.cs @@ -25,7 +25,7 @@ public async Task Should_Emit_Events_In_Correct_Order_For_Tool_Using_Conversatio var session = await CreateSessionAsync(); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { @@ -55,7 +55,7 @@ public async Task Should_Include_Valid_Fields_On_All_Events() { var session = await CreateSessionAsync(); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { @@ -91,7 +91,7 @@ public async Task Should_Emit_Assistant_Usage_Event_After_Model_Call() { var session = await CreateSessionAsync(); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { @@ -114,7 +114,7 @@ public async Task Should_Emit_Session_Usage_Info_Event_After_Model_Call() { var session = await CreateSessionAsync(); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { @@ -163,7 +163,7 @@ public async Task Should_Emit_Tool_Execution_Events_With_Correct_Fields() var session = await CreateSessionAsync(); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { @@ -194,7 +194,7 @@ public async Task Should_Emit_Assistant_Message_With_MessageId() { var session = await CreateSessionAsync(); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { diff --git a/dotnet/test/E2E/ModeHandlersE2ETests.cs b/dotnet/test/E2E/ModeHandlersE2ETests.cs index 3f7ec47c8..badbfc942 100644 --- a/dotnet/test/E2E/ModeHandlersE2ETests.cs +++ b/dotnet/test/E2E/ModeHandlersE2ETests.cs @@ -176,7 +176,7 @@ private static async Task GetNextEventOfTypeAllowingRateLimitAsync( var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var cts = new CancellationTokenSource(timeout ?? TimeSpan.FromSeconds(30)); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { if (evt is T matched && predicate(matched)) { diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index 115565816..ae4233031 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -112,7 +112,7 @@ public async Task Client_Receives_Commands_Changed_When_Another_Client_Joins_Wit var commandsChangedTcs = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); - using var sub = session1.On(evt => + using var sub = session1.On(evt => { if (evt is CommandsChangedEvent changed) { @@ -160,7 +160,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici var capChangedTcs = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); - using var sub = session1.On(evt => + using var sub = session1.On(evt => { if (evt is CapabilitiesChangedEvent capEvt) { @@ -206,7 +206,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec var capEnabledTcs = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); - using var subEnabled = session1.On(evt => + using var subEnabled = session1.On(evt => { if (evt is CapabilitiesChangedEvent { Data.Ui.Elicitation: true }) { @@ -242,7 +242,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec var capDisabledTcs = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); - using var subDisabled = session1.On(evt => + using var subDisabled = session1.On(evt => { if (evt is CapabilitiesChangedEvent { Data.Ui.Elicitation: false }) { diff --git a/dotnet/test/E2E/MultiClientE2ETests.cs b/dotnet/test/E2E/MultiClientE2ETests.cs index bd939a6cf..70a0e56d1 100644 --- a/dotnet/test/E2E/MultiClientE2ETests.cs +++ b/dotnet/test/E2E/MultiClientE2ETests.cs @@ -113,12 +113,12 @@ public async Task Both_Clients_See_Tool_Request_And_Completion_Events() var client1Completed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var client2Completed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using var sub1 = session1.On(evt => + using var sub1 = session1.On(evt => { if (evt is ExternalToolRequestedEvent) client1Requested.TrySetResult(true); if (evt is ExternalToolCompletedEvent) client1Completed.TrySetResult(true); }); - using var sub2 = session2.On(evt => + using var sub2 = session2.On(evt => { if (evt is ExternalToolRequestedEvent) client2Requested.TrySetResult(true); if (evt is ExternalToolCompletedEvent) client2Completed.TrySetResult(true); @@ -173,8 +173,8 @@ public async Task One_Client_Approves_Permission_And_Both_See_The_Result() var client1PermissionCompleted = TestHelper.GetNextEventOfTypeAsync(session1); var client2PermissionCompleted = TestHelper.GetNextEventOfTypeAsync(session2); - using var sub1 = session1.On(evt => client1Events.Add(evt)); - using var sub2 = session2.On(evt => client2Events.Add(evt)); + using var sub1 = session1.On(evt => client1Events.Add(evt)); + using var sub2 = session2.On(evt => client2Events.Add(evt)); await session1.SendAsync(new MessageOptions { @@ -223,8 +223,8 @@ public async Task One_Client_Rejects_Permission_And_Both_See_The_Result() // Wait for PermissionCompletedEvent on client2 which may arrive slightly after session1 goes idle var client2PermissionCompleted = TestHelper.GetNextEventOfTypeAsync(session2); - using var sub1 = session1.On(evt => client1Events.Add(evt)); - using var sub2 = session2.On(evt => client2Events.Add(evt)); + using var sub1 = session1.On(evt => client1Events.Add(evt)); + using var sub2 = session2.On(evt => client2Events.Add(evt)); // Write a file so the agent has something to edit await File.WriteAllTextAsync(Path.Combine(Ctx.WorkDir, "protected.txt"), "protected content"); diff --git a/dotnet/test/E2E/MultiTurnE2ETests.cs b/dotnet/test/E2E/MultiTurnE2ETests.cs index b10acfbc2..91e1d2ebe 100644 --- a/dotnet/test/E2E/MultiTurnE2ETests.cs +++ b/dotnet/test/E2E/MultiTurnE2ETests.cs @@ -23,7 +23,7 @@ public async Task Should_Use_Tool_Results_From_Previous_Turns() var session = await CreateSessionAsync(); var events = new List(); var eventsLock = new object(); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { lock (eventsLock) { @@ -52,7 +52,7 @@ public async Task Should_Handle_File_Creation_Then_Reading_Across_Turns() var session = await CreateSessionAsync(); var events = new List(); var eventsLock = new object(); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { lock (eventsLock) { diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index 7f0620976..693b042fb 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -421,7 +421,7 @@ private static async Task> WaitFo TaskCreationOptions.RunContinuationsAsynchronously); using var cts = new CancellationTokenSource(PendingWorkTimeout); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { if (evt is ExternalToolRequestedEvent toolEvent && expected.Contains(toolEvent.Data.ToolName)) { diff --git a/dotnet/test/E2E/PermissionE2ETests.cs b/dotnet/test/E2E/PermissionE2ETests.cs index 9dd7a549f..edfe170f7 100644 --- a/dotnet/test/E2E/PermissionE2ETests.cs +++ b/dotnet/test/E2E/PermissionE2ETests.cs @@ -100,7 +100,7 @@ public async Task Should_Deny_Permission_When_Handler_Returns_Denied() // for the reject decision, which lets us assert the decision was honored // — not merely that the operation didn't happen. var userRejectedToolCall = false; - session.On(evt => + session.On(evt => { if (evt is ToolExecutionCompleteEvent toolEvt && !toolEvt.Data.Success && @@ -139,7 +139,7 @@ public async Task Should_Deny_Tool_Operations_When_Handler_Explicitly_Denies() }); var permissionDenied = false; - session.On(evt => + session.On(evt => { if (evt is ToolExecutionCompleteEvent toolEvt && !toolEvt.Data.Success && @@ -266,7 +266,7 @@ public async Task Should_Deny_Tool_Operations_When_Handler_Explicitly_Denies_Aft }); var permissionDenied = false; - session2.On(evt => + session2.On(evt => { if (evt is ToolExecutionCompleteEvent toolEvt && !toolEvt.Data.Success && @@ -344,7 +344,7 @@ void AddLifecycleEvent(string phase, string? toolCallId) } }); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { switch (evt) { @@ -442,7 +442,7 @@ public async Task Should_Handle_Concurrent_Permission_Requests_From_Parallel_Too } }); - session.On(evt => + session.On(evt => { if (evt is ToolExecutionCompleteEvent toolEvt) { @@ -554,7 +554,7 @@ public async Task Should_Short_Circuit_Permission_Handler_When_Set_Approve_All_E try { var toolCompleted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { if (evt is ToolExecutionCompleteEvent done && done.Data.Success) { diff --git a/dotnet/test/E2E/SessionE2ETests.cs b/dotnet/test/E2E/SessionE2ETests.cs index 339f3b013..9e042633c 100644 --- a/dotnet/test/E2E/SessionE2ETests.cs +++ b/dotnet/test/E2E/SessionE2ETests.cs @@ -324,7 +324,7 @@ public async Task Should_Receive_Session_Events() var concurrentCount = 0; var maxConcurrent = 0; - session.On(evt => + session.On(evt => { // Track concurrent handler invocations to verify serial dispatch. var current = Interlocked.Increment(ref concurrentCount); @@ -393,7 +393,7 @@ public async Task Send_Returns_Immediately_While_Events_Stream_In_Background() }); var events = new ConcurrentQueue(); - session.On(evt => events.Enqueue(evt.Type)); + session.On(evt => events.Enqueue(evt.Type)); // Use a slow command so we can verify SendAsync() returns before completion await session.SendAsync(new MessageOptions { Prompt = "Run 'sleep 2 && echo done'" }); @@ -415,7 +415,7 @@ public async Task SendAndWait_Blocks_Until_Session_Idle_And_Returns_Final_Assist var session = await CreateSessionAsync(); var events = new ConcurrentQueue(); - session.On(evt => events.Enqueue(evt.Type)); + session.On(evt => events.Enqueue(evt.Type)); var response = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2+2?" }); @@ -581,7 +581,7 @@ public async Task Should_Log_Messages_At_Various_Levels() var session = await CreateSessionAsync(); var events = new List(); var eventsLock = new object(); - session.On(evt => + session.On(evt => { lock (eventsLock) { @@ -640,7 +640,7 @@ public async Task Handler_Exception_Does_Not_Halt_Event_Delivery() var eventCount = 0; var gotIdle = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - session.On(evt => + session.On(evt => { eventCount++; @@ -666,7 +666,7 @@ public async Task DisposeAsync_From_Handler_Does_Not_Deadlock() var session = await CreateSessionAsync(); var disposed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - session.On(evt => + session.On(evt => { if (evt is UserMessageEvent) { diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index 1d53dfb15..acc3fd640 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -370,7 +370,7 @@ public async Task Should_Succeed_With_Compaction_While_Using_SessionFs() }); SessionCompactionCompleteEvent? compactionEvent = null; - using var _ = session.On(evt => + using var _ = session.On(evt => { if (evt is SessionCompactionCompleteEvent complete) { diff --git a/dotnet/test/E2E/SessionFsSqliteE2ETests.cs b/dotnet/test/E2E/SessionFsSqliteE2ETests.cs index cdb9873aa..9d0787b37 100644 --- a/dotnet/test/E2E/SessionFsSqliteE2ETests.cs +++ b/dotnet/test/E2E/SessionFsSqliteE2ETests.cs @@ -68,7 +68,7 @@ public async Task Should_Allow_Subagents_To_Use_Sql_Tool_Via_Inherited_Sessionfs }); var events = new List(); - using var _ = session.On(evt => events.Add(evt)); + using var _ = session.On(evt => events.Add(evt)); await session.SendAndWaitAsync(new MessageOptions { diff --git a/dotnet/test/E2E/SessionLifecycleE2ETests.cs b/dotnet/test/E2E/SessionLifecycleE2ETests.cs index f35ade93d..3864134cf 100644 --- a/dotnet/test/E2E/SessionLifecycleE2ETests.cs +++ b/dotnet/test/E2E/SessionLifecycleE2ETests.cs @@ -130,8 +130,8 @@ public async Task Should_Isolate_Events_Between_Concurrent_Sessions() var session1Events = new List(); var session2Events = new List(); - session1.On(evt => { lock (session1Events) { session1Events.Add(evt); } }); - session2.On(evt => { lock (session2Events) { session2Events.Add(evt); } }); + session1.On(evt => { lock (session1Events) { session1Events.Add(evt); } }); + session2.On(evt => { lock (session2Events) { session2Events.Add(evt); } }); // Send to both sessions await session1.SendAndWaitAsync(new MessageOptions diff --git a/dotnet/test/E2E/StreamingFidelityE2ETests.cs b/dotnet/test/E2E/StreamingFidelityE2ETests.cs index 6c6de81d8..119c76d0d 100644 --- a/dotnet/test/E2E/StreamingFidelityE2ETests.cs +++ b/dotnet/test/E2E/StreamingFidelityE2ETests.cs @@ -15,7 +15,7 @@ public async Task Should_Produce_Delta_Events_When_Streaming_Is_Enabled() var session = await CreateSessionAsync(new SessionConfig { Streaming = true }); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { Prompt = "Count from 1 to 5, separated by commas." }); @@ -51,7 +51,7 @@ public async Task Should_Not_Produce_Deltas_When_Streaming_Is_Disabled() var session = await CreateSessionAsync(new SessionConfig { Streaming = false }); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { Prompt = "Say 'hello world'." }); @@ -83,7 +83,7 @@ public async Task Should_Produce_Deltas_After_Session_Resume() new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, Streaming = true }); var events = new List(); - session2.On(evt => { lock (events) { events.Add(evt); } }); + session2.On(evt => { lock (events) { events.Add(evt); } }); var answer = await session2.SendAndWaitAsync(new MessageOptions { Prompt = "Now if you double that, what do you get?" }); Assert.NotNull(answer); @@ -118,7 +118,7 @@ public async Task Should_Not_Produce_Deltas_After_Session_Resume_With_Streaming_ new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, Streaming = false }); var events = new List(); - session2.On(evt => { lock (events) { events.Add(evt); } }); + session2.On(evt => { lock (events) { events.Add(evt); } }); var answer = await session2.SendAndWaitAsync(new MessageOptions { Prompt = "Now if you double that, what do you get?" }); Assert.NotNull(answer); @@ -150,7 +150,7 @@ public async Task Should_Emit_Streaming_Deltas_With_Reasoning_Effort_Configured( }); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 15 * 17?" }); @@ -180,7 +180,7 @@ public async Task Should_Emit_AssistantMessageStart_Before_Deltas_With_Matching_ var session = await CreateSessionAsync(new SessionConfig { Streaming = true }); var events = new List(); - session.On(evt => { lock (events) { events.Add(evt); } }); + session.On(evt => { lock (events) { events.Add(evt); } }); await session.SendAndWaitAsync(new MessageOptions { Prompt = "Count from 1 to 5, separated by commas." }); diff --git a/dotnet/test/E2E/SuspendE2ETests.cs b/dotnet/test/E2E/SuspendE2ETests.cs index 44dcef7dd..92ea9be50 100644 --- a/dotnet/test/E2E/SuspendE2ETests.cs +++ b/dotnet/test/E2E/SuspendE2ETests.cs @@ -175,7 +175,7 @@ public async Task Should_Reject_Pending_External_Tool_When_Suspending() OnPermissionRequest = PermissionHandler.ApproveAll, }); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { if (evt is ExternalToolRequestedEvent ext && ext.Data.ToolName == "suspend_reject_external_tool") { diff --git a/dotnet/test/E2E/ToolResultsE2ETests.cs b/dotnet/test/E2E/ToolResultsE2ETests.cs index ae2454a64..8762b4d2a 100644 --- a/dotnet/test/E2E/ToolResultsE2ETests.cs +++ b/dotnet/test/E2E/ToolResultsE2ETests.cs @@ -131,7 +131,7 @@ public async Task Should_Handle_Tool_Result_With_Rejected_ResultType() OnPermissionRequest = PermissionHandler.ApproveAll, }); - session.On(evt => + session.On(evt => { if (evt is ToolExecutionCompleteEvent toolEvt) { @@ -181,7 +181,7 @@ public async Task Should_Handle_Tool_Result_With_Denied_ResultType() OnPermissionRequest = PermissionHandler.ApproveAll, }); - session.On(evt => + session.On(evt => { if (evt is ToolExecutionCompleteEvent toolEvt) { diff --git a/dotnet/test/Harness/TestHelper.cs b/dotnet/test/Harness/TestHelper.cs index f8b6114e9..e974b7dd3 100644 --- a/dotnet/test/Harness/TestHelper.cs +++ b/dotnet/test/Harness/TestHelper.cs @@ -40,7 +40,7 @@ void TryComplete() if (snapshot != null && idle) tcs.TrySetResult(snapshot); } - using var subscription = session.On(evt => + using var subscription = session.On(evt => { switch (evt) { @@ -127,7 +127,7 @@ public static async Task GetNextEventOfTypeAsync( var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); using var cts = new CancellationTokenSource(timeout ?? DefaultEventTimeout); - using var subscription = session.On(evt => + using var subscription = session.On(evt => { if (evt is T matched && predicate(matched)) { From aa4481b5ecf36a372566d9e0e071b30da49d8012 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 14:52:49 +0100 Subject: [PATCH 09/40] Phase 4g: DateTimeOffset timestamps + PermissionRequestResult.Feedback - Add UnixMillisecondsDateTimeOffsetConverter for unix-millis-as-JSON-number timestamps - Convert long Timestamp fields on hook *Input* types and PingResponse to DateTimeOffset via the new converter - Convert SessionLifecycleEventMetadata.StartTime/ModifiedTime from ISO 8601 strings to DateTimeOffset - Convert SessionMetadata.StartTime/ModifiedTime from DateTime to DateTimeOffset - Add PermissionRequestResult.Feedback property (parity with the RPC PermissionDecisionReject type's feedback field); forward to the wire only on reject decisions - Tidy XML doc on PermissionRequestResult.Kind to reference the well-known PermissionRequestResultKind static members directly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Session.cs | 5 +- dotnet/src/Types.cs | 50 ++++++++++++------- ...UnixMillisecondsDateTimeOffsetConverter.cs | 22 ++++++++ .../E2E/HookLifecycleAndOutputE2ETests.cs | 6 +-- 4 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 74b9af946..9232fdeb1 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -755,7 +755,10 @@ private async Task ExecutePermissionAndRespondAsync(string requestId, Permission return; } var responseRpcTimestamp = Stopwatch.GetTimestamp(); - await Rpc.Permissions.HandlePendingPermissionRequestAsync(requestId, new PermissionDecision { Kind = result.Kind.Value }); + PermissionDecision decision = result.Kind == PermissionRequestResultKind.Rejected + ? new PermissionDecisionReject { Feedback = result.Feedback } + : new PermissionDecision { Kind = result.Kind.Value }; + await Rpc.Permissions.HandlePendingPermissionRequestAsync(requestId, decision); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, "CopilotSession.ExecutePermissionAndRespondAsync response sent successfully. Elapsed={Elapsed}, SessionId={SessionId}, RequestId={RequestId}", responseRpcTimestamp, diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index e8d4dfcfc..da49d16e2 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -689,13 +689,13 @@ public override void Write(Utf8JsonWriter writer, PermissionRequestResultKind va public sealed class PermissionRequestResult { /// - /// Permission decision kind. Use the static members of - /// to construct values. Valid kinds are: + /// Permission decision kind. Construct values with the static members on + /// : /// - /// "approve-once" () — allow this single request. - /// "reject" () — deny the request. - /// "user-not-available" () — deny because no user is available to confirm. - /// "no-result" () — leave the pending request unanswered (protocol v1 only; rejected by protocol v2 servers). + /// — allow this single request. + /// — deny the request. + /// — deny because no user is available to confirm. + /// — leave the pending request unanswered (protocol v1 only; rejected by protocol v2 servers). /// /// [JsonPropertyName("kind")] @@ -706,6 +706,14 @@ public sealed class PermissionRequestResult /// [JsonPropertyName("rules")] public IList? Rules { get; set; } + + /// + /// Optional human-readable feedback to forward to the LLM along with the + /// decision. Mirrors the feedback field on the RPC-level + /// type. + /// + [JsonPropertyName("feedback")] + public string? Feedback { get; set; } } /// @@ -1167,7 +1175,8 @@ public sealed class PreToolUseHookInput /// Unix timestamp in milliseconds when the tool use was initiated. /// [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + [JsonConverter(typeof(UnixMillisecondsDateTimeOffsetConverter))] + public DateTimeOffset Timestamp { get; set; } /// /// Current working directory of the session. @@ -1249,7 +1258,8 @@ public sealed class PostToolUseHookInput /// Unix timestamp in milliseconds when the tool execution completed. /// [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + [JsonConverter(typeof(UnixMillisecondsDateTimeOffsetConverter))] + public DateTimeOffset Timestamp { get; set; } /// /// Current working directory of the session. @@ -1320,7 +1330,8 @@ public sealed class UserPromptSubmittedHookInput /// Unix timestamp in milliseconds when the prompt was submitted. /// [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + [JsonConverter(typeof(UnixMillisecondsDateTimeOffsetConverter))] + public DateTimeOffset Timestamp { get; set; } /// /// Current working directory of the session. @@ -1379,7 +1390,8 @@ public sealed class SessionStartHookInput /// Unix timestamp in milliseconds when the session started. /// [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + [JsonConverter(typeof(UnixMillisecondsDateTimeOffsetConverter))] + public DateTimeOffset Timestamp { get; set; } /// /// Current working directory of the session. @@ -1443,7 +1455,8 @@ public sealed class SessionEndHookInput /// Unix timestamp in milliseconds when the session ended. /// [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + [JsonConverter(typeof(UnixMillisecondsDateTimeOffsetConverter))] + public DateTimeOffset Timestamp { get; set; } /// /// Current working directory of the session. @@ -1521,7 +1534,8 @@ public sealed class ErrorOccurredHookInput /// Unix timestamp in milliseconds when the error occurred. /// [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + [JsonConverter(typeof(UnixMillisecondsDateTimeOffsetConverter))] + public DateTimeOffset Timestamp { get; set; } /// /// Current working directory of the session. @@ -2831,11 +2845,11 @@ public sealed class SessionMetadata /// /// Time when the session was created. /// - public DateTime StartTime { get; set; } + public DateTimeOffset StartTime { get; set; } /// /// Time when the session was last modified. /// - public DateTime ModifiedTime { get; set; } + public DateTimeOffset ModifiedTime { get; set; } /// /// Human-readable summary of the session. /// @@ -3092,16 +3106,16 @@ public sealed class GetModelsResponse public sealed class SessionLifecycleEventMetadata { /// - /// ISO 8601 timestamp when the session was created. + /// Timestamp when the session was created. /// [JsonPropertyName("startTime")] - public string StartTime { get; set; } = string.Empty; + public DateTimeOffset StartTime { get; set; } /// - /// ISO 8601 timestamp when the session was last modified. + /// Timestamp when the session was last modified. /// [JsonPropertyName("modifiedTime")] - public string ModifiedTime { get; set; } = string.Empty; + public DateTimeOffset ModifiedTime { get; set; } /// /// Human-readable summary of the session. diff --git a/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs b/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs new file mode 100644 index 000000000..2245d5ebd --- /dev/null +++ b/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace GitHub.Copilot.SDK; + +/// Converts between JSON numeric milliseconds-since-Unix-epoch and . +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed class UnixMillisecondsDateTimeOffsetConverter : JsonConverter +{ + /// + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + DateTimeOffset.FromUnixTimeMilliseconds(reader.GetInt64()); + + /// + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) => + writer.WriteNumberValue(value.ToUnixTimeMilliseconds()); +} diff --git a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs index 6bb589391..ca1f78734 100644 --- a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs +++ b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs @@ -43,7 +43,7 @@ public async Task Should_Invoke_OnSessionStart_Hook_On_New_Session() Assert.NotEmpty(sessionStartInputs); Assert.Equal("new", sessionStartInputs[0].Source); - Assert.True(sessionStartInputs[0].Timestamp > 0); + Assert.True(sessionStartInputs[0].Timestamp > DateTimeOffset.UnixEpoch); Assert.False(string.IsNullOrEmpty(sessionStartInputs[0].Cwd)); await session.DisposeAsync(); @@ -71,7 +71,7 @@ public async Task Should_Invoke_OnUserPromptSubmitted_Hook_When_Sending_A_Messag Assert.NotEmpty(userPromptInputs); Assert.Contains("Say hello", userPromptInputs[0].Prompt); - Assert.True(userPromptInputs[0].Timestamp > 0); + Assert.True(userPromptInputs[0].Timestamp > DateTimeOffset.UnixEpoch); Assert.False(string.IsNullOrEmpty(userPromptInputs[0].Cwd)); await session.DisposeAsync(); @@ -116,7 +116,7 @@ public async Task Should_Invoke_OnErrorOccurred_Hook_When_Error_Occurs() OnErrorOccurred = (input, invocation) => { Assert.Equal(session!.SessionId, invocation.SessionId); - Assert.True(input.Timestamp > 0); + Assert.True(input.Timestamp > DateTimeOffset.UnixEpoch); Assert.False(string.IsNullOrEmpty(input.Cwd)); Assert.False(string.IsNullOrEmpty(input.Error)); Assert.Contains(input.ErrorContext, ValidErrorContexts); From c8e2573071f9170186918671916df935b8e6026a Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 14:56:34 +0100 Subject: [PATCH 10/40] Phase 7: SendAsync(string) / SendAndWaitAsync(string) convenience overloads Most SDK uses end up looking like SendAsync(new MessageOptions { Prompt = ... }); add a plain-prompt overload that wraps it. Per ApiView #258. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Session.cs | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 9232fdeb1..15f0172e1 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -191,7 +191,34 @@ private Task InvokeRpcAsync(string method, object?[]? args, CancellationTo } /// - /// Sends a message to the Copilot session and waits for the response. + /// Sends a plain-text user message and returns the message ID without waiting for + /// the assistant to reply. Convenience overload for . + /// + /// The user message text. + /// A that can be used to cancel the operation. + /// A task that resolves with the message ID. + public Task SendAsync(string prompt, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(prompt); + return SendAsync(new MessageOptions { Prompt = prompt }, cancellationToken); + } + + /// + /// Sends a plain-text user message and waits until the session becomes idle. + /// Convenience overload for . + /// + /// The user message text. + /// Timeout duration (default: 60 seconds). + /// A that can be used to cancel the operation. + /// A task that resolves with the final assistant message event, or null if none was received. + public Task SendAndWaitAsync(string prompt, TimeSpan? timeout = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(prompt); + return SendAndWaitAsync(new MessageOptions { Prompt = prompt }, timeout, cancellationToken); + } + + /// + /// Sends a message to the Copilot session. /// /// Options for the message to be sent, including the prompt and optional attachments. /// A that can be used to cancel the operation. @@ -199,11 +226,11 @@ private Task InvokeRpcAsync(string method, object?[]? args, CancellationTo /// Thrown if the session has been disposed. /// /// - /// This method returns immediately after the message is queued. Use + /// This method returns immediately after the message is queued. Use /// if you need to wait for the assistant to finish processing. /// /// - /// Subscribe to events via to receive streaming responses and other session events. + /// Subscribe to events via to receive streaming responses and other session events. /// /// /// @@ -260,12 +287,12 @@ public async Task SendAsync(MessageOptions options, CancellationToken ca /// Thrown if the session has been disposed. /// /// - /// This is a convenience method that combines with waiting for + /// This is a convenience method that combines with waiting for /// the session.idle event. Use this when you want to block until the assistant /// has finished processing the message. /// /// - /// Events are still delivered to handlers registered via while waiting. + /// Events are still delivered to handlers registered via while waiting. /// /// /// @@ -1449,7 +1476,7 @@ public async Task LogAsync(string message, SessionLogLevel? level = null, bool? /// A task representing the dispose operation. /// /// - /// The caller should ensure the session is idle (e.g., + /// The caller should ensure the session is idle (e.g., /// has returned) before disposing. If the session is not idle, in-flight event handlers /// or tool handlers may observe failures. /// From 3907f283f7276d1a241fb479dd3eb6ffc2333be3 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 15:02:01 +0100 Subject: [PATCH 11/40] Phase 9 (partial): rename Cwd/Remote properties on hand-written types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CopilotClientOptions.Cwd -> WorkingDirectory - CopilotClientOptions.Remote -> EnableRemoteSessions - McpStdioServerConfig.Cwd -> WorkingDirectory (wire name stays 'cwd') - SessionListFilter.Cwd -> WorkingDirectory Full CLI/server -> runtime terminology overhaul (the RuntimeConnection discriminated config and removal of flat CliPath/CliArgs/Port/UseStdio/CliUrl properties) is deferred — it requires substantial restructuring of the connection-routing logic in Client.cs and warrants its own change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 2 +- dotnet/src/Client.cs | 4 ++-- dotnet/src/Types.cs | 14 +++++++------- dotnet/test/E2E/ClientOptionsE2ETests.cs | 2 +- .../test/E2E/SessionMcpAndAgentConfigE2ETests.cs | 4 ++-- dotnet/test/Harness/E2ETestContext.cs | 2 +- dotnet/test/Unit/CloneTests.cs | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dotnet/README.md b/dotnet/README.md index 42ea340c1..93c78c10e 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -79,7 +79,7 @@ new CopilotClient(CopilotClientOptions? options = null) - `UseStdio` - Use stdio transport instead of TCP (default: true) - `LogLevel` - Log level (default: "info") - `AutoStart` - Auto-start server (default: true) -- `Cwd` - Working directory for the CLI process +- `WorkingDirectory` - Working directory for the CLI process - `CopilotHome` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned CLI process. When not set, the CLI defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when using `CliUrl`. - `Environment` - Environment variables to pass to the CLI process - `Logger` - `ILogger` instance for SDK logging diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 081ac0ccb..5f3344c1f 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -1384,7 +1384,7 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) args.AddRange(["--session-idle-timeout", options.SessionIdleTimeoutSeconds.Value.ToString(CultureInfo.InvariantCulture)]); } - if (options.Remote) + if (options.EnableRemoteSessions) { args.Add("--remote"); } @@ -1401,7 +1401,7 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) RedirectStandardInput = options.UseStdio == true, RedirectStandardOutput = true, RedirectStandardError = true, - WorkingDirectory = options.Cwd, + WorkingDirectory = options.WorkingDirectory, CreateNoWindow = true }; diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index da49d16e2..6212a644e 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -127,7 +127,7 @@ protected CopilotClientOptions(CopilotClientOptions? other) CliArgs = (string[]?)other.CliArgs?.Clone(); CliPath = other.CliPath; CliUrl = other.CliUrl; - Cwd = other.Cwd; + WorkingDirectory = other.WorkingDirectory; CopilotHome = other.CopilotHome; Environment = other.Environment; GitHubToken = other.GitHubToken; @@ -141,7 +141,7 @@ protected CopilotClientOptions(CopilotClientOptions? other) SessionFs = other.SessionFs; SessionIdleTimeoutSeconds = other.SessionIdleTimeoutSeconds; TcpConnectionToken = other.TcpConnectionToken; - Remote = other.Remote; + EnableRemoteSessions = other.EnableRemoteSessions; } /// @@ -155,7 +155,7 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// /// Working directory for the CLI process. /// - public string? Cwd { get; set; } + public string? WorkingDirectory { get; set; } /// /// Base directory for Copilot data (session state, config, etc.). /// Sets the COPILOT_HOME environment variable on the spawned CLI process. @@ -257,7 +257,7 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// This option is only used when the SDK spawns the CLI process; it is ignored /// when connecting to an external server via . /// - public bool Remote { get; set; } + public bool EnableRemoteSessions { get; set; } /// /// Creates a shallow clone of this instance. @@ -1939,7 +1939,7 @@ public sealed class McpStdioServerConfig : McpServerConfig /// Working directory for the server process. /// [JsonPropertyName("cwd")] - public string? Cwd { get; set; } + public string? WorkingDirectory { get; set; } } /// @@ -2823,8 +2823,8 @@ public sealed class SessionContext /// public sealed class SessionListFilter { - /// Filter by exact cwd match. - public string? Cwd { get; set; } + /// Filter by exact working directory match. + public string? WorkingDirectory { get; set; } /// Filter by git root. public string? GitRoot { get; set; } /// Filter by repository (owner/repo format). diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index a3a418c50..4ca22f62f 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -42,7 +42,7 @@ public async Task Should_Use_Client_Cwd_For_Default_WorkingDirectory() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - Cwd = clientCwd, + WorkingDirectory = clientCwd, }); var session = await client.CreateSessionAsync(new SessionConfig diff --git a/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs b/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs index cc528b219..475508065 100644 --- a/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs +++ b/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs @@ -297,7 +297,7 @@ public async Task Should_Pass_Literal_Env_Values_To_Mcp_Server_Subprocess() Command = "node", Args = [Path.Combine(testHarnessDir, "test-mcp-server.mjs")], Env = new Dictionary { ["TEST_SECRET"] = "hunter2" }, - Cwd = testHarnessDir, + WorkingDirectory = testHarnessDir, Tools = ["*"] } }; @@ -358,7 +358,7 @@ await File.WriteAllTextAsync( "--config", configPath ], - Cwd = testHarnessDir, + WorkingDirectory = testHarnessDir, Tools = ["*"] } }; diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index ef703c4be..5c69e4320 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -212,7 +212,7 @@ public CopilotClient CreateClient( { options ??= new CopilotClientOptions(); - options.Cwd ??= WorkDir; + options.WorkingDirectory ??= WorkDir; options.Environment ??= GetEnvironment(); options.UseStdio = useStdio; options.Logger ??= Logger; diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 3779332d2..29f4241ce 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -15,7 +15,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() { CliPath = "/usr/bin/copilot", CliArgs = ["--verbose", "--debug"], - Cwd = "/home/user", + WorkingDirectory = "/home/user", Port = 8080, UseStdio = false, CliUrl = "http://localhost:8080", @@ -24,7 +24,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() GitHubToken = "ghp_test", UseLoggedInUser = false, CopilotHome = "/custom/copilot/home", - Remote = true, + EnableRemoteSessions = true, SessionIdleTimeoutSeconds = 600, }; @@ -32,7 +32,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() Assert.Equal(original.CliPath, clone.CliPath); Assert.Equal(original.CliArgs, clone.CliArgs); - Assert.Equal(original.Cwd, clone.Cwd); + Assert.Equal(original.WorkingDirectory, clone.WorkingDirectory); Assert.Equal(original.Port, clone.Port); Assert.Equal(original.UseStdio, clone.UseStdio); Assert.Equal(original.CliUrl, clone.CliUrl); @@ -41,7 +41,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() Assert.Equal(original.GitHubToken, clone.GitHubToken); Assert.Equal(original.UseLoggedInUser, clone.UseLoggedInUser); Assert.Equal(original.CopilotHome, clone.CopilotHome); - Assert.Equal(original.Remote, clone.Remote); + Assert.Equal(original.EnableRemoteSessions, clone.EnableRemoteSessions); Assert.Equal(original.SessionIdleTimeoutSeconds, clone.SessionIdleTimeoutSeconds); } From 85ee59f25b58dee91b73a0ddbff84496005cb974 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 15:05:56 +0100 Subject: [PATCH 12/40] Phase 8: README updates for OnLifecycle and lifecycle event types Replace stale references to SessionLifecycleEventTypes constants with the new typed hierarchy (SessionCreatedEvent / SessionDeletedEvent / etc.). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 24 ++++++++----------- .../E2E/HookLifecycleAndOutputE2ETests.cs | 3 ++- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/dotnet/README.md b/dotnet/README.md index 93c78c10e..10989f04d 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -153,23 +153,19 @@ Get the ID of the session currently displayed in the TUI. Only available when co Request the TUI to switch to displaying the specified session. Only available in TUI+server mode. -##### `On(Action handler): IDisposable` +##### `OnLifecycle(Action handler): IDisposable where T : SessionLifecycleEvent` -Subscribe to all session lifecycle events. Returns an `IDisposable` that unsubscribes when disposed. +Subscribe to session lifecycle events. Pass a derived type to filter by kind, or `SessionLifecycleEvent` to receive every lifecycle event. Returns an `IDisposable` that unsubscribes when disposed. ```csharp +// Receive every lifecycle event: using var subscription = client.OnLifecycle(evt => { Console.WriteLine($"Session {evt.SessionId}: {evt.Type}"); }); -``` - -##### `On(string eventType, Action handler): IDisposable` -Subscribe to a specific lifecycle event type. Use `SessionLifecycleEventTypes` constants. - -```csharp -using var subscription = client.OnLifecycle(evt => +// Only receive foreground events: +using var foreground = client.OnLifecycle(evt => { Console.WriteLine($"Session {evt.SessionId} is now in foreground"); }); @@ -177,11 +173,11 @@ using var subscription = client.OnLifecycle(evt => **Lifecycle Event Types:** -- `SessionLifecycleEventTypes.Created` - A new session was created -- `SessionLifecycleEventTypes.Deleted` - A session was deleted -- `SessionLifecycleEventTypes.Updated` - A session was updated -- `SessionLifecycleEventTypes.Foreground` - A session became the foreground session in TUI -- `SessionLifecycleEventTypes.Background` - A session is no longer the foreground session +- `SessionCreatedEvent` — A new session was created +- `SessionDeletedEvent` — A session was deleted +- `SessionUpdatedEvent` — A session was updated +- `SessionForegroundEvent` — A session became the foreground session in TUI +- `SessionBackgroundEvent` — A session is no longer the foreground session --- diff --git a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs index ca1f78734..b18af00ad 100644 --- a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs +++ b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs @@ -3,6 +3,7 @@ *--------------------------------------------------------------------------------------------*/ using Microsoft.Extensions.AI; +using System.Text.Json; using Xunit; using Xunit.Abstractions; @@ -326,7 +327,7 @@ public async Task Should_Allow_PostToolUse_To_Return_ModifiedResult() { TextResultForLlm = "modified by post hook", ResultType = "success", - ToolTelemetry = new Dictionary(), + ToolTelemetry = new Dictionary(), }, SuppressOutput = false, }); From 89f002abe37225eab21fdd710b03609a0e8b68f6 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 15:26:41 +0100 Subject: [PATCH 13/40] Phase 5: extract SessionConfigBase; seal config classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New abstract SessionConfigBase holds the 32 properties duplicated between SessionConfig and ResumeSessionConfig, plus the shared copy-constructor logic. - SessionConfig now contains only SessionId + Cloud. - ResumeSessionConfig now contains only SuppressResumeEvent + ContinuePendingWork. - SessionConfig, ResumeSessionConfig, CopilotClientOptions, and MessageOptions are now sealed. Each has a private copy constructor + non-virtual Clone() method (was protected/virtual to allow subclassing — no longer a goal). - Updated references from SessionConfig.X to SessionConfigBase.X where the property lives on the base. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/CopilotTool.cs | 2 +- dotnet/src/Types.cs | 450 +++++++------------------------------- 2 files changed, 79 insertions(+), 373 deletions(-) diff --git a/dotnet/src/CopilotTool.cs b/dotnet/src/CopilotTool.cs index 6adcee093..59f1d126b 100644 --- a/dotnet/src/CopilotTool.cs +++ b/dotnet/src/CopilotTool.cs @@ -23,7 +23,7 @@ public static class CopilotTool /// The delegate to invoke when the tool is called. /// The Microsoft.Extensions.AI options used to create the function. /// Copilot-specific tool options. - /// An that can be added to or . + /// An that can be added to . /// /// This is a helper on top of that applies additional configuration to support /// Copilot tools, such as binding a parameter and adding Copilot-specific metadata properties based on the provided diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 6212a644e..46a613360 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -109,7 +109,7 @@ internal static class Diagnostics /// /// Configuration options for creating a instance. /// -public class CopilotClientOptions +public sealed class CopilotClientOptions { /// /// Initializes a new instance of the class. @@ -120,7 +120,7 @@ public CopilotClientOptions() { } /// Initializes a new instance of the class /// by copying the properties of the specified instance. /// - protected CopilotClientOptions(CopilotClientOptions? other) + private CopilotClientOptions(CopilotClientOptions? other) { if (other is null) return; @@ -224,7 +224,7 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// Custom session filesystem provider configuration. /// When set, the client registers as the session filesystem provider on connect, /// routing session-scoped file I/O through per-session handlers created via - /// or . + /// . /// public SessionFsConfig? SessionFs { get; set; } @@ -268,7 +268,7 @@ protected CopilotClientOptions(CopilotClientOptions? other) /// Other reference-type properties (for example delegates and the logger) are not /// deep-cloned; the original and the clone will share those objects. /// - public virtual CopilotClientOptions Clone() + public CopilotClientOptions Clone() { return new(this); } @@ -1813,7 +1813,7 @@ public sealed class ProviderConfig /// Well-known model name used by the runtime to look up agent configuration /// (tools, prompts, reasoning behavior) and default token limits. Also used /// as the wire model when is not set. - /// Falls back to . + /// Falls back to . /// [JsonPropertyName("modelId")] public string? ModelId { get; set; } @@ -1822,7 +1822,7 @@ public sealed class ProviderConfig /// Model name sent to the provider API for inference. Use this when the /// provider's model name (e.g. an Azure deployment name or a custom /// fine-tune name) differs from . - /// Falls back to , then . + /// Falls back to , then . /// [JsonPropertyName("wireModel")] public string? WireModel { get; set; } @@ -2037,7 +2037,7 @@ public sealed class CustomAgentConfig /// List of skill names to preload into this agent's context. /// When set, the full content of each listed skill is eagerly injected into /// the agent's context at startup. Skills are resolved by name from the - /// session's configured skill directories (). + /// session's configured skill directories (). /// When omitted, no skills are injected (opt-in model). /// [JsonPropertyName("skills")] @@ -2124,20 +2124,20 @@ public sealed class CloudSessionOptions } /// -/// Configuration options for creating a new Copilot session. +/// Shared configuration properties for creating or resuming a Copilot session. +/// Use when creating a new session, or +/// when resuming an existing one. /// -public class SessionConfig +public abstract class SessionConfigBase { - /// - /// Initializes a new instance of the class. - /// - public SessionConfig() { } + /// Initializes a new instance of the class. + protected SessionConfigBase() { } /// - /// Initializes a new instance of the class - /// by copying the properties of the specified instance. + /// Initializes a new instance of by copying the + /// properties of the specified instance. /// - protected SessionConfig(SessionConfig? other) + protected SessionConfigBase(SessionConfigBase? other) { if (other is null) return; @@ -2172,8 +2172,6 @@ protected SessionConfig(SessionConfig? other) CreateSessionFsProvider = other.CreateSessionFsProvider; GitHubToken = other.GitHubToken; RemoteSession = other.RemoteSession; - Cloud = other.Cloud; - SessionId = other.SessionId; SkillDirectories = other.SkillDirectories is not null ? [.. other.SkillDirectories] : null; InstructionDirectories = other.InstructionDirectories is not null ? [.. other.InstructionDirectories] : null; Streaming = other.Streaming; @@ -2183,20 +2181,10 @@ protected SessionConfig(SessionConfig? other) WorkingDirectory = other.WorkingDirectory; } - /// - /// Optional session identifier; a new ID is generated if not provided. - /// - public string? SessionId { get; set; } - - /// - /// Client name to identify the application using the SDK. - /// Included in the User-Agent header for API requests. - /// + /// Client name to identify the application using the SDK. public string? ClientName { get; set; } - /// - /// Model identifier to use for this session (e.g., "gpt-4o"). - /// + /// Model identifier to use for this session (e.g., "gpt-4o"). public string? Model { get; set; } /// @@ -2206,9 +2194,7 @@ protected SessionConfig(SessionConfig? other) /// public string? ReasoningEffort { get; set; } - /// - /// Per-property overrides for model capabilities, deep-merged over runtime defaults. - /// + /// Per-property overrides for model capabilities, deep-merged over runtime defaults. public ModelCapabilitiesOverride? ModelCapabilities { get; set; } /// @@ -2236,21 +2222,17 @@ protected SessionConfig(SessionConfig? other) /// are left for the client to handle via external tool request events. /// public ICollection? Tools { get; set; } - /// - /// System message configuration for the session. - /// + + /// System message configuration for the session. public SystemMessageConfig? SystemMessage { get; set; } - /// - /// List of tool names to allow; only these tools will be available when specified. - /// + + /// List of tool names to allow; only these tools will be available when specified. public IList? AvailableTools { get; set; } - /// - /// List of tool names to exclude from the session. - /// + + /// List of tool names to exclude from the session. public IList? ExcludedTools { get; set; } - /// - /// Custom model provider configuration for the session. - /// + + /// Custom model provider configuration for the session. public ProviderConfig? Provider { get; set; } /// @@ -2264,52 +2246,28 @@ protected SessionConfig(SessionConfig? other) /// public bool? EnableSessionTelemetry { get; set; } - /// - /// Handler for permission requests from the server. - /// When provided, the server will call this handler to request permission for operations. - /// + /// Handler for permission requests from the server. public PermissionRequestHandler? OnPermissionRequest { get; set; } - /// - /// Handler for user input requests from the agent. - /// When provided, enables the ask_user tool for the agent to request user input. - /// + /// Handler for user input requests from the agent. public UserInputHandler? OnUserInputRequest { get; set; } - /// - /// Slash commands registered for this session. - /// When the CLI has a TUI, each command appears as /name for the user to invoke. - /// The handler is called when the user executes the command. - /// + /// Slash commands registered for this session. public IList? Commands { get; set; } - /// - /// Handler for elicitation requests from the server or MCP tools. - /// When provided, the server will route elicitation requests to this handler - /// and report elicitation as a supported capability. - /// + /// Handler for elicitation requests from the server or MCP tools. public ElicitationHandler? OnElicitationRequest { get; set; } - /// - /// Handler for exit-plan-mode requests from the server. - /// When provided, the server will route exitPlanMode.request callbacks to this handler. - /// + /// Handler for exit-plan-mode requests from the server. public ExitPlanModeHandler? OnExitPlanModeRequest { get; set; } - /// - /// Handler for auto-mode-switch requests from the server. - /// When provided, the server will route autoModeSwitch.request callbacks to this handler. - /// + /// Handler for auto-mode-switch requests from the server. public AutoModeSwitchHandler? OnAutoModeSwitchRequest { get; set; } - /// - /// Hook handlers for session lifecycle events. - /// + /// Hook handlers for session lifecycle events. public SessionHooks? Hooks { get; set; } - /// - /// Working directory for the session. - /// + /// Working directory for the session. public string? WorkingDirectory { get; set; } /// @@ -2337,9 +2295,7 @@ protected SessionConfig(SessionConfig? other) /// public IDictionary? McpServers { get; set; } - /// - /// Custom agent configurations for the session. - /// + /// Custom agent configurations for the session. public IList? CustomAgents { get; set; } /// @@ -2355,19 +2311,13 @@ protected SessionConfig(SessionConfig? other) /// public string? Agent { get; set; } - /// - /// Directories to load skills from. - /// + /// Directories to load skills from. public IList? SkillDirectories { get; set; } - /// - /// Additional directories to search for custom instruction files. - /// + /// Additional directories to search for custom instruction files. public IList? InstructionDirectories { get; set; } - /// - /// List of skill names to disable. - /// + /// List of skill names to disable. public IList? DisabledSkills { get; set; } /// @@ -2377,15 +2327,9 @@ protected SessionConfig(SessionConfig? other) public InfiniteSessionConfig? InfiniteSessions { get; set; } /// - /// Optional event handler that is registered on the session before the - /// session.create RPC is issued. + /// Optional event handler registered on the session before the session.create / session.resume + /// RPC is issued, ensuring early events are delivered. /// - /// - /// Equivalent to calling immediately - /// after creation, but executes earlier in the lifecycle so no events are missed. - /// Using this property rather than guarantees that early events emitted - /// by the CLI during session creation (e.g. session.start) are delivered to the handler. - /// public Action? OnEvent { get; set; } /// @@ -2410,6 +2354,30 @@ protected SessionConfig(SessionConfig? other) /// /// public RemoteSessionMode? RemoteSession { get; set; } +} + +/// +/// Configuration options for creating a new Copilot session. +/// +public sealed class SessionConfig : SessionConfigBase +{ + /// Initializes a new instance of the class. + public SessionConfig() { } + + /// + /// Initializes a new instance of by copying the + /// properties of the specified instance. + /// + private SessionConfig(SessionConfig? other) : base(other) + { + if (other is null) return; + + SessionId = other.SessionId; + Cloud = other.Cloud; + } + + /// Optional session identifier; a new ID is generated if not provided. + public string? SessionId { get; set; } /// /// Creates a remote session in the cloud instead of a local session. @@ -2427,200 +2395,29 @@ protected SessionConfig(SessionConfig? other) /// hooks, infinite session configuration, and delegates) are not deep-cloned; the original /// and the clone will share those nested objects, and changes to them may affect both. /// - public virtual SessionConfig Clone() - { - return new(this); - } + public SessionConfig Clone() => new(this); } /// /// Configuration options for resuming an existing Copilot session. /// -public class ResumeSessionConfig +public sealed class ResumeSessionConfig : SessionConfigBase { - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. public ResumeSessionConfig() { } /// - /// Initializes a new instance of the class - /// by copying the properties of the specified instance. + /// Initializes a new instance of by copying the + /// properties of the specified instance. /// - protected ResumeSessionConfig(ResumeSessionConfig? other) + private ResumeSessionConfig(ResumeSessionConfig? other) : base(other) { if (other is null) return; - AvailableTools = other.AvailableTools is not null ? [.. other.AvailableTools] : null; - ClientName = other.ClientName; - Commands = other.Commands is not null ? [.. other.Commands] : null; - ConfigDir = other.ConfigDir; - CustomAgents = other.CustomAgents is not null ? [.. other.CustomAgents] : null; - DefaultAgent = other.DefaultAgent; - Agent = other.Agent; - DisabledSkills = other.DisabledSkills is not null ? [.. other.DisabledSkills] : null; SuppressResumeEvent = other.SuppressResumeEvent; - EnableConfigDiscovery = other.EnableConfigDiscovery; ContinuePendingWork = other.ContinuePendingWork; - ExcludedTools = other.ExcludedTools is not null ? [.. other.ExcludedTools] : null; - Hooks = other.Hooks; - InfiniteSessions = other.InfiniteSessions; - McpServers = other.McpServers is not null - ? (other.McpServers is Dictionary dict - ? new Dictionary(dict, dict.Comparer) - : new Dictionary(other.McpServers)) - : null; - Model = other.Model; - ModelCapabilities = other.ModelCapabilities; - OnAutoModeSwitchRequest = other.OnAutoModeSwitchRequest; - OnElicitationRequest = other.OnElicitationRequest; - OnEvent = other.OnEvent; - OnExitPlanModeRequest = other.OnExitPlanModeRequest; - OnPermissionRequest = other.OnPermissionRequest; - OnUserInputRequest = other.OnUserInputRequest; - Provider = other.Provider; - EnableSessionTelemetry = other.EnableSessionTelemetry; - ReasoningEffort = other.ReasoningEffort; - CreateSessionFsProvider = other.CreateSessionFsProvider; - GitHubToken = other.GitHubToken; - RemoteSession = other.RemoteSession; - SkillDirectories = other.SkillDirectories is not null ? [.. other.SkillDirectories] : null; - InstructionDirectories = other.InstructionDirectories is not null ? [.. other.InstructionDirectories] : null; - Streaming = other.Streaming; - IncludeSubAgentStreamingEvents = other.IncludeSubAgentStreamingEvents; - SystemMessage = other.SystemMessage; - Tools = other.Tools is not null ? [.. other.Tools] : null; - WorkingDirectory = other.WorkingDirectory; } - /// - /// Client name to identify the application using the SDK. - /// Included in the User-Agent header for API requests. - /// - public string? ClientName { get; set; } - - /// - /// Model to use for this session. Can change the model when resuming. - /// - public string? Model { get; set; } - - /// - /// Custom tool declarations available to the language model during the resumed session. - /// Declarations backed by an are invoked automatically; declarations without one - /// are left for the client to handle via external tool request events. - /// - public ICollection? Tools { get; set; } - - /// - /// System message configuration. - /// - public SystemMessageConfig? SystemMessage { get; set; } - - /// - /// List of tool names to allow. When specified, only these tools will be available. - /// Takes precedence over ExcludedTools. - /// - public IList? AvailableTools { get; set; } - - /// - /// List of tool names to disable. All other tools remain available. - /// Ignored if AvailableTools is specified. - /// - public IList? ExcludedTools { get; set; } - - /// - /// Custom model provider configuration for the resumed session. - /// - public ProviderConfig? Provider { get; set; } - - /// - /// Enables or disables internal session telemetry for this session. - /// When false, disables session telemetry. When null (the default) or true, - /// telemetry is enabled for GitHub-authenticated sessions. - /// When a custom (BYOK) is configured, session telemetry is - /// always disabled regardless of this setting. - /// This is independent of , which configures - /// OpenTelemetry export for observability. - /// - public bool? EnableSessionTelemetry { get; set; } - - /// - /// Reasoning effort level for models that support it. - /// Valid values: "low", "medium", "high", "xhigh". - /// - public string? ReasoningEffort { get; set; } - - /// - /// Per-property overrides for model capabilities, deep-merged over runtime defaults. - /// - public ModelCapabilitiesOverride? ModelCapabilities { get; set; } - - /// - /// Handler for permission requests from the server. - /// When provided, the server will call this handler to request permission for operations. - /// - public PermissionRequestHandler? OnPermissionRequest { get; set; } - - /// - /// Handler for user input requests from the agent. - /// When provided, enables the ask_user tool for the agent to request user input. - /// - public UserInputHandler? OnUserInputRequest { get; set; } - - /// - /// Slash commands registered for this session. - /// When the CLI has a TUI, each command appears as /name for the user to invoke. - /// The handler is called when the user executes the command. - /// - public IList? Commands { get; set; } - - /// - /// Handler for elicitation requests from the server or MCP tools. - /// When provided, the server will route elicitation requests to this handler - /// and report elicitation as a supported capability. - /// - public ElicitationHandler? OnElicitationRequest { get; set; } - - /// - /// Handler for exit-plan-mode requests from the server. - /// When provided, the server will route exitPlanMode.request callbacks to this handler. - /// - public ExitPlanModeHandler? OnExitPlanModeRequest { get; set; } - - /// - /// Handler for auto-mode-switch requests from the server. - /// When provided, the server will route autoModeSwitch.request callbacks to this handler. - /// - public AutoModeSwitchHandler? OnAutoModeSwitchRequest { get; set; } - - /// - /// Hook handlers for session lifecycle events. - /// - public SessionHooks? Hooks { get; set; } - - /// - /// Working directory for the session. - /// - public string? WorkingDirectory { get; set; } - - /// - /// Override the default configuration directory location. - /// - public string? ConfigDir { get; set; } - - /// - /// When , automatically discovers MCP server configurations - /// (e.g. .mcp.json, .vscode/mcp.json) and skill directories from - /// the working directory and merges them with any explicitly provided - /// and , with explicit - /// values taking precedence on name collision. - /// - /// Custom instruction files (.github/copilot-instructions.md, AGENTS.md, etc.) - /// are always loaded from the working directory regardless of this setting. - /// - /// - public bool? EnableConfigDiscovery { get; set; } - /// /// When true, the session.resume event is not emitted. /// Default: false (resume event is emitted). @@ -2634,101 +2431,13 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// interrupted on resume. /// /// For permission requests, the runtime re-emits permission.requested so the - /// registered handler can re-prompt; for external - /// tool calls, the consumer is expected to supply the result via the corresponding - /// low-level RPC method. + /// registered handler can re-prompt; + /// for external tool calls, the consumer is expected to supply the result via the + /// corresponding low-level RPC method. /// /// public bool? ContinuePendingWork { get; set; } - /// - /// Enable streaming of assistant message and reasoning chunks. - /// When true, assistant.message_delta and assistant.reasoning_delta events - /// with deltaContent are sent as the response is generated. - /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public bool? Streaming { get; set; } - - /// - /// Include sub-agent streaming events in the event stream. When true, streaming - /// delta events from sub-agents (e.g., assistant.message_delta, - /// assistant.reasoning_delta, assistant.streaming_delta with - /// agentId set) are forwarded to this connection. When false, only - /// non-streaming sub-agent events and subagent.* lifecycle events are - /// forwarded; streaming deltas from sub-agents are suppressed. - /// Default: true. - /// - public bool IncludeSubAgentStreamingEvents { get; set; } = true; - - /// - /// MCP server configurations for the session. - /// Keys are server names, values are server configurations ( or ). - /// - public IDictionary? McpServers { get; set; } - - /// - /// Custom agent configurations for the session. - /// - public IList? CustomAgents { get; set; } - - /// - /// Configuration for the default agent (the built-in agent that handles turns when no custom agent is selected). - /// Use to hide specific tools from the default agent - /// while keeping them available to custom sub-agents. - /// - public DefaultAgentConfig? DefaultAgent { get; set; } - - /// - /// Name of the custom agent to activate when the session starts. - /// Must match the of one of the agents in . - /// - public string? Agent { get; set; } - - /// - /// Directories to load skills from. - /// - public IList? SkillDirectories { get; set; } - - /// - /// Additional directories to search for custom instruction files. - /// - public IList? InstructionDirectories { get; set; } - - /// - /// List of skill names to disable. - /// - public IList? DisabledSkills { get; set; } - - /// - /// Infinite session configuration for persistent workspaces and automatic compaction. - /// - public InfiniteSessionConfig? InfiniteSessions { get; set; } - - /// - /// Optional event handler registered before the session.resume RPC is issued, - /// ensuring early events are delivered. See . - /// - public Action? OnEvent { get; set; } - - /// - /// Supplies a handler for session filesystem operations. - /// This is used only when is configured. - /// - public Func? CreateSessionFsProvider { get; set; } - - /// - /// GitHub token for per-session authentication. - /// When provided, the runtime resolves this token into a full GitHub identity - /// and stores it on the session for content exclusion, model routing, and quota checks. - /// - public string? GitHubToken { get; set; } - - /// - /// Per-session remote behavior control. - /// See for details. - /// - public RemoteSessionMode? RemoteSession { get; set; } - /// /// Creates a shallow clone of this instance. /// @@ -2739,16 +2448,13 @@ protected ResumeSessionConfig(ResumeSessionConfig? other) /// hooks, infinite session configuration, and delegates) are not deep-cloned; the original /// and the clone will share those nested objects, and changes to them may affect both. /// - public virtual ResumeSessionConfig Clone() - { - return new(this); - } + public ResumeSessionConfig Clone() => new(this); } /// /// Options for sending a message in a Copilot session. /// -public class MessageOptions +public sealed class MessageOptions { /// /// Initializes a new instance of the class. @@ -2759,7 +2465,7 @@ public MessageOptions() { } /// Initializes a new instance of the class /// by copying the properties of the specified instance. /// - protected MessageOptions(MessageOptions? other) + private MessageOptions(MessageOptions? other) { if (other is null) return; @@ -2797,7 +2503,7 @@ protected MessageOptions(MessageOptions? other) /// Other reference-type properties (for example attachment items) are not deep-cloned; /// the original and the clone will share those nested objects. /// - public virtual MessageOptions Clone() + public MessageOptions Clone() { return new(this); } From 3061cb2b052814f004e107b67c19802c452052a9 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 15:31:38 +0100 Subject: [PATCH 14/40] Phase 6: remove named delegate types, use Func<...> Drop these 13 named delegate types in favor of inline Func<...>: - ToolHandler (unused; just deleted) - PermissionRequestHandler -> Func> - UserInputHandler - ExitPlanModeHandler - AutoModeSwitchHandler - CommandHandler -> Func - ElicitationHandler -> Func> - PreToolUseHandler / PostToolUseHandler / UserPromptSubmittedHandler - SessionStartHandler / SessionEndHandler / ErrorOccurredHandler Lambdas at call sites are unaffected (target-typed). The PermissionHandler static class keeps its ApproveAll preset; the property type is now Func<...>. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/PermissionHandlers.cs | 6 +- dotnet/src/Session.cs | 24 +++---- dotnet/src/Types.cs | 91 ++++---------------------- dotnet/test/E2E/ElicitationE2ETests.cs | 4 +- 4 files changed, 30 insertions(+), 95 deletions(-) diff --git a/dotnet/src/PermissionHandlers.cs b/dotnet/src/PermissionHandlers.cs index 3a40e7244..a3d76bcb5 100644 --- a/dotnet/src/PermissionHandlers.cs +++ b/dotnet/src/PermissionHandlers.cs @@ -4,10 +4,10 @@ namespace GitHub.Copilot.SDK; -/// Provides pre-built implementations. +/// Provides pre-built permission request handlers. public static class PermissionHandler { - /// A that approves all permission requests. - public static PermissionRequestHandler ApproveAll { get; } = + /// A permission handler that approves all permission requests. + public static Func> ApproveAll { get; } = (_, _) => Task.FromResult(new PermissionRequestResult { Kind = PermissionRequestResultKind.Approved }); } diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 15f0172e1..5e19baa53 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -56,15 +56,15 @@ namespace GitHub.Copilot.SDK; public sealed partial class CopilotSession : IAsyncDisposable { private readonly Dictionary _toolHandlers = []; - private readonly Dictionary _commandHandlers = []; + private readonly Dictionary> _commandHandlers = []; private readonly ILogger _logger; private readonly CopilotClient _parentClient; - private volatile PermissionRequestHandler? _permissionHandler; - private volatile UserInputHandler? _userInputHandler; - private volatile ElicitationHandler? _elicitationHandler; - private volatile ExitPlanModeHandler? _exitPlanModeHandler; - private volatile AutoModeSwitchHandler? _autoModeSwitchHandler; + private volatile Func>? _permissionHandler; + private volatile Func>? _userInputHandler; + private volatile Func>? _elicitationHandler; + private volatile Func>? _exitPlanModeHandler; + private volatile Func>? _autoModeSwitchHandler; private ImmutableArray _eventHandlers = ImmutableArray.Empty; private sealed record EventSubscription(Type EventType, Action Handler); @@ -535,7 +535,7 @@ internal void RegisterTools(ICollection tools) /// When the assistant needs permission to perform certain actions (e.g., file operations), /// this handler is called to approve or deny the request. /// - internal void RegisterPermissionHandler(PermissionRequestHandler? handler) + internal void RegisterPermissionHandler(Func>? handler) { _permissionHandler = handler; } @@ -761,7 +761,7 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, /// /// Executes a permission handler and sends the result back via the HandlePendingPermissionRequest RPC. /// - private async Task ExecutePermissionAndRespondAsync(string requestId, PermissionRequest permissionRequest, PermissionRequestHandler handler) + private async Task ExecutePermissionAndRespondAsync(string requestId, PermissionRequest permissionRequest, Func> handler) { try { @@ -816,7 +816,7 @@ private async Task ExecutePermissionAndRespondAsync(string requestId, Permission /// Registers a handler for user input requests from the agent. /// /// The handler to invoke when user input is requested. - internal void RegisterUserInputHandler(UserInputHandler handler) + internal void RegisterUserInputHandler(Func> handler) { _userInputHandler = handler; } @@ -839,7 +839,7 @@ internal void RegisterCommands(IEnumerable? commands) /// Registers an elicitation handler for this session. /// /// The handler to invoke when an elicitation request is received. - internal void RegisterElicitationHandler(ElicitationHandler? handler) + internal void RegisterElicitationHandler(Func>? handler) { _elicitationHandler = handler; } @@ -848,7 +848,7 @@ internal void RegisterElicitationHandler(ElicitationHandler? handler) /// Registers an exit-plan-mode handler for this session. /// /// The handler to invoke when an exit-plan-mode request is received. - internal void RegisterExitPlanModeHandler(ExitPlanModeHandler? handler) + internal void RegisterExitPlanModeHandler(Func>? handler) { _exitPlanModeHandler = handler; } @@ -857,7 +857,7 @@ internal void RegisterExitPlanModeHandler(ExitPlanModeHandler? handler) /// Registers an auto-mode-switch handler for this session. /// /// The handler to invoke when an auto-mode-switch request is received. - internal void RegisterAutoModeSwitchHandler(AutoModeSwitchHandler? handler) + internal void RegisterAutoModeSwitchHandler(Func>? handler) { _autoModeSwitchHandler = handler; } diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 46a613360..b7004854e 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -606,11 +606,6 @@ public sealed class ToolInvocation public JsonElement? Arguments { get; set; } } -/// -/// Delegate for handling tool invocations and returning a result. -/// -public delegate Task ToolHandler(ToolInvocation invocation); - /// Describes the kind of a permission request result. [JsonConverter(typeof(PermissionRequestResultKind.Converter))] [DebuggerDisplay("{Value,nq}")] @@ -727,11 +722,6 @@ public sealed class PermissionInvocation public string SessionId { get; set; } = string.Empty; } -/// -/// Delegate for handling permission requests and returning a decision. -/// -public delegate Task PermissionRequestHandler(PermissionRequest request, PermissionInvocation invocation); - // ============================================================================ // User Input Handler Types // ============================================================================ @@ -789,11 +779,6 @@ public sealed class UserInputInvocation public string SessionId { get; set; } = string.Empty; } -/// -/// Handler for user input requests from the agent. -/// -public delegate Task UserInputHandler(UserInputRequest request, UserInputInvocation invocation); - /// /// Request to exit plan mode and continue with a selected action. /// @@ -859,11 +844,6 @@ public sealed class ExitPlanModeInvocation public string SessionId { get; set; } = string.Empty; } -/// -/// Handler for exit-plan-mode requests from the agent. -/// -public delegate Task ExitPlanModeHandler(ExitPlanModeRequest request, ExitPlanModeInvocation invocation); - /// /// Request to switch to auto mode after an eligible rate limit. /// @@ -893,11 +873,6 @@ public sealed class AutoModeSwitchInvocation public string SessionId { get; set; } = string.Empty; } -/// -/// Handler for auto-mode-switch requests from the agent. -/// -public delegate Task AutoModeSwitchHandler(AutoModeSwitchRequest request, AutoModeSwitchInvocation invocation); - // ============================================================================ // Command Handler Types // ============================================================================ @@ -920,11 +895,11 @@ public sealed class CommandDefinition /// /// Handler invoked when the command is executed. /// - public required CommandHandler Handler { get; set; } + public required Func Handler { get; set; } } /// -/// Context passed to a when a command is executed. +/// Context passed to a command handler when a command is executed. /// public sealed class CommandContext { @@ -949,11 +924,6 @@ public sealed class CommandContext public string Args { get; set; } = string.Empty; } -/// -/// Delegate for handling slash-command executions. -/// -public delegate Task CommandHandler(CommandContext context); - // ============================================================================ // Elicitation Types (UI — client → server) // ============================================================================ @@ -1114,11 +1084,6 @@ public sealed class ElicitationContext public string? Url { get; set; } } -/// -/// Delegate for handling elicitation requests from the server. -/// -public delegate Task ElicitationHandler(ElicitationContext context); - // ============================================================================ // Session Capabilities // ============================================================================ @@ -1238,11 +1203,6 @@ public sealed class PreToolUseHookOutput public bool? SuppressOutput { get; set; } } -/// -/// Delegate invoked before a tool is executed, allowing modification or denial of the call. -/// -public delegate Task PreToolUseHandler(PreToolUseHookInput input, HookInvocation invocation); - /// /// Input for a post-tool-use hook. /// @@ -1310,11 +1270,6 @@ public sealed class PostToolUseHookOutput public bool? SuppressOutput { get; set; } } -/// -/// Delegate invoked after a tool has been executed, allowing modification of the result. -/// -public delegate Task PostToolUseHandler(PostToolUseHookInput input, HookInvocation invocation); - /// /// Input for a user-prompt-submitted hook. /// @@ -1370,11 +1325,6 @@ public sealed class UserPromptSubmittedHookOutput public bool? SuppressOutput { get; set; } } -/// -/// Delegate invoked when the user submits a prompt, allowing modification of the prompt. -/// -public delegate Task UserPromptSubmittedHandler(UserPromptSubmittedHookInput input, HookInvocation invocation); - /// /// Input for a session-start hook. /// @@ -1435,11 +1385,6 @@ public sealed class SessionStartHookOutput public IDictionary? ModifiedConfig { get; set; } } -/// -/// Delegate invoked when a session starts, allowing injection of context or config changes. -/// -public delegate Task SessionStartHandler(SessionStartHookInput input, HookInvocation invocation); - /// /// Input for a session-end hook. /// @@ -1514,11 +1459,6 @@ public sealed class SessionEndHookOutput public string? SessionSummary { get; set; } } -/// -/// Delegate invoked when a session ends, allowing cleanup actions or summary generation. -/// -public delegate Task SessionEndHandler(SessionEndHookInput input, HookInvocation invocation); - /// /// Input for an error-occurred hook. /// @@ -1603,11 +1543,6 @@ public sealed class ErrorOccurredHookOutput public string? UserNotification { get; set; } } -/// -/// Delegate invoked when an error occurs, allowing custom error handling strategies. -/// -public delegate Task ErrorOccurredHandler(ErrorOccurredHookInput input, HookInvocation invocation); - /// /// Hook handlers configuration for a session. /// @@ -1616,32 +1551,32 @@ public sealed class SessionHooks /// /// Handler called before a tool is executed. /// - public PreToolUseHandler? OnPreToolUse { get; set; } + public Func>? OnPreToolUse { get; set; } /// /// Handler called after a tool has been executed. /// - public PostToolUseHandler? OnPostToolUse { get; set; } + public Func>? OnPostToolUse { get; set; } /// /// Handler called when the user submits a prompt. /// - public UserPromptSubmittedHandler? OnUserPromptSubmitted { get; set; } + public Func>? OnUserPromptSubmitted { get; set; } /// /// Handler called when a session starts. /// - public SessionStartHandler? OnSessionStart { get; set; } + public Func>? OnSessionStart { get; set; } /// /// Handler called when a session ends. /// - public SessionEndHandler? OnSessionEnd { get; set; } + public Func>? OnSessionEnd { get; set; } /// /// Handler called when an error occurs. /// - public ErrorOccurredHandler? OnErrorOccurred { get; set; } + public Func>? OnErrorOccurred { get; set; } } /// @@ -2247,22 +2182,22 @@ protected SessionConfigBase(SessionConfigBase? other) public bool? EnableSessionTelemetry { get; set; } /// Handler for permission requests from the server. - public PermissionRequestHandler? OnPermissionRequest { get; set; } + public Func>? OnPermissionRequest { get; set; } /// Handler for user input requests from the agent. - public UserInputHandler? OnUserInputRequest { get; set; } + public Func>? OnUserInputRequest { get; set; } /// Slash commands registered for this session. public IList? Commands { get; set; } /// Handler for elicitation requests from the server or MCP tools. - public ElicitationHandler? OnElicitationRequest { get; set; } + public Func>? OnElicitationRequest { get; set; } /// Handler for exit-plan-mode requests from the server. - public ExitPlanModeHandler? OnExitPlanModeRequest { get; set; } + public Func>? OnExitPlanModeRequest { get; set; } /// Handler for auto-mode-switch requests from the server. - public AutoModeSwitchHandler? OnAutoModeSwitchRequest { get; set; } + public Func>? OnAutoModeSwitchRequest { get; set; } /// Hook handlers for session lifecycle events. public SessionHooks? Hooks { get; set; } diff --git a/dotnet/test/E2E/ElicitationE2ETests.cs b/dotnet/test/E2E/ElicitationE2ETests.cs index 3af2547e3..9e705d639 100644 --- a/dotnet/test/E2E/ElicitationE2ETests.cs +++ b/dotnet/test/E2E/ElicitationE2ETests.cs @@ -381,7 +381,7 @@ public void ElicitationContext_Has_All_Properties() [Fact] public async Task Session_Config_OnElicitationRequest_Is_Cloned() { - ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult + Func> handler = _ => Task.FromResult(new ElicitationResult { Action = UIElicitationResponseAction.Cancel, }); @@ -400,7 +400,7 @@ public async Task Session_Config_OnElicitationRequest_Is_Cloned() [Fact] public void Resume_Config_OnElicitationRequest_Is_Cloned() { - ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult + Func> handler = _ => Task.FromResult(new ElicitationResult { Action = UIElicitationResponseAction.Cancel, }); From 3daed1391ba0163ec72ee626520181b88d87f543 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 16:03:52 +0100 Subject: [PATCH 15/40] Phase 9: introduce RuntimeConnection discriminated config Replaces the flat CliPath/CliArgs/Port/UseStdio/CliUrl/TcpConnectionToken properties on CopilotClientOptions with a single Connection property of type RuntimeConnection, constructed via factory methods: - RuntimeConnection.Stdio(path?, args?) - spawns runtime over stdio (default) - RuntimeConnection.Tcp(port=0, connectionToken?, path?, args?) - spawns runtime listening on TCP. port=0 auto-allocates; port-in-use is an error. - RuntimeConnection.Uri(url, connectionToken?) - connects to an already running runtime; does not spawn. The 'exactly one mode' invariant is now encoded by the type hierarchy (ChildProcessRuntimeConnection abstract base for the spawning kinds, plus UriRuntimeConnection for the connect-to-existing case). Connection token only exists on Tcp/Uri (Stdio doesn't need one). Concrete subclasses have internal ctors so factory methods are the only way to construct. Client.cs stores the RuntimeConnection directly and pattern-matches on the subtype at the connection-routing points (no separate flat fields). Also: - Rename CopilotClient.ActualPort -> RuntimePort. - Rename CopilotClientOptions.CopilotHome -> BaseDirectory. - README updated to describe the new Connection model and removed flags. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 32 +-- dotnet/src/Client.cs | 154 +++++++------- dotnet/src/Types.cs | 188 ++++++++++++------ dotnet/test/ConnectionTokenTests.cs | 20 +- dotnet/test/E2E/ClientE2ETests.cs | 32 +-- dotnet/test/E2E/ClientOptionsE2ETests.cs | 45 ++--- .../MultiClientCommandsElicitationE2ETests.cs | 16 +- dotnet/test/E2E/MultiClientE2ETests.cs | 14 +- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 38 ++-- .../test/E2E/RpcExtensionsLoadedE2ETests.cs | 2 +- dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs | 4 +- dotnet/test/E2E/SessionFsE2ETests.cs | 9 +- dotnet/test/E2E/SuspendE2ETests.cs | 8 +- dotnet/test/Harness/E2ETestBase.cs | 5 +- dotnet/test/Harness/E2ETestContext.cs | 20 +- dotnet/test/Harness/E2ETestFixture.cs | 2 +- .../test/Unit/ClientSessionLifetimeTests.cs | 14 +- dotnet/test/Unit/CloneTests.cs | 32 +-- 18 files changed, 335 insertions(+), 300 deletions(-) diff --git a/dotnet/README.md b/dotnet/README.md index 10989f04d..159f5e7e2 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -72,20 +72,24 @@ new CopilotClient(CopilotClientOptions? options = null) **Options:** -- `CliPath` - Path to CLI executable (default: `COPILOT_CLI_PATH` env var, or bundled CLI) -- `CliArgs` - Extra arguments prepended before SDK-managed flags -- `CliUrl` - URL of existing CLI server to connect to (e.g., `"localhost:8080"`). When provided, the client will not spawn a CLI process. -- `Port` - Server port (default: 0 for random) -- `UseStdio` - Use stdio transport instead of TCP (default: true) -- `LogLevel` - Log level (default: "info") -- `AutoStart` - Auto-start server (default: true) -- `WorkingDirectory` - Working directory for the CLI process -- `CopilotHome` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned CLI process. When not set, the CLI defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when using `CliUrl`. -- `Environment` - Environment variables to pass to the CLI process -- `Logger` - `ILogger` instance for SDK logging +- `Connection` - How to connect to the Copilot runtime. Defaults to `null` (equivalent to `RuntimeConnection.Stdio()` with the bundled runtime). See "RuntimeConnection" below. +- `LogLevel` - Runtime log level. Accepts well-known values `CopilotLogLevel.None`, `Error`, `Warning`, `Info`, `Debug`, `All`. Defaults to null (the runtime's own default). +- `WorkingDirectory` - Working directory for the runtime process. +- `BaseDirectory` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned runtime process. When not set, the runtime defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when connecting via `RuntimeConnection.Uri(...)`. +- `EnableRemoteSessions` - Enables remote-session features. +- `Environment` - Environment variables to pass to the runtime process. +- `Logger` - `ILogger` instance for SDK logging. - `GitHubToken` - GitHub token for authentication. When provided, takes priority over other auth methods. -- `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `CliUrl`. -- `Telemetry` - OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. +- `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `RuntimeConnection.Uri(...)`. +- `Telemetry` - OpenTelemetry configuration for the runtime process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. + +#### RuntimeConnection + +`CopilotClientOptions.Connection` describes how the SDK reaches a Copilot runtime. There are three flavors, all constructed via static factories: + +- `RuntimeConnection.Stdio(path?, args?)` — spawns the runtime as a child process and communicates over stdio. This is the default when `Connection` is null. +- `RuntimeConnection.Tcp(port = 0, connectionToken?, path?, args?)` — spawns the runtime as a child process listening on a TCP port. `port = 0` auto-allocates; if a non-zero port is already in use, startup fails (no fallback). Use `CopilotClient.RuntimePort` after `StartAsync` to read the assigned port. `connectionToken` is required if other clients will connect via `RuntimeConnection.Uri(...)`. +- `RuntimeConnection.Uri(url, connectionToken?)` — connects to an already-running runtime at `url` (e.g., `"localhost:8080"`). Does not spawn a process. #### Methods @@ -983,7 +987,7 @@ catch (Exception ex) ## Requirements - .NET 8.0 or later -- GitHub Copilot CLI installed and in PATH (or provide custom `CliPath`) +- GitHub Copilot CLI installed and in PATH (or provide custom `Connection = RuntimeConnection.Stdio(path: ...)`) ## License diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 5f3344c1f..56f9a8d15 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -71,12 +71,12 @@ public sealed partial class CopilotClient : IDisposable, IAsyncDisposable internal readonly ConcurrentDictionary _sessions = new(); private readonly CopilotClientOptions _options; + private readonly RuntimeConnection _connection; private readonly ILogger _logger; private Task? _connectionTask; private bool _disposed; private readonly int? _optionsPort; private readonly string? _optionsHost; - private readonly string? _effectiveConnectionToken; private int? _actualPort; private int? _negotiatedProtocolVersion; private List? _modelsCache; @@ -101,27 +101,26 @@ private sealed record LifecycleSubscription(Type EventType, Action - /// Gets the actual TCP port the CLI server is listening on, if using TCP transport. + /// Gets the actual TCP port the runtime is listening on, if using TCP transport. /// - public int? ActualPort => _actualPort; + public int? RuntimePort => _actualPort; /// /// Creates a new instance of . /// /// Options for creating the client. If null, default options are used. - /// Thrown when mutually exclusive options are provided (e.g., CliUrl with UseStdio or CliPath). /// /// - /// // Default options - spawns CLI server using stdio + /// // Default options - spawns the bundled runtime using stdio /// var client = new CopilotClient(); /// - /// // Connect to an existing server - /// var client = new CopilotClient(new CopilotClientOptions { CliUrl = "localhost:3000", UseStdio = false }); + /// // Connect to an existing runtime + /// var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri("localhost:3000") }); /// - /// // Custom CLI path with specific log level + /// // Custom runtime path with specific log level /// var client = new CopilotClient(new CopilotClientOptions /// { - /// CliPath = "/usr/local/bin/copilot", + /// Connection = RuntimeConnection.Stdio(path: "/usr/local/bin/copilot"), /// LogLevel = CopilotLogLevel.Debug /// }); /// @@ -129,63 +128,50 @@ private sealed record LifecycleSubscription(Type EventType, Action - /// Parses a CLI URL into a URI with host and port. + /// Parses a runtime URL into a URI with host and port. /// /// The URL to parse. Supports formats: "port", "host:port", "http://host:port". - /// A containing the parsed host and port. - private static Uri ParseCliUrl(string url) + private static Uri ParseRuntimeUrl(string url) { // If it's just a port number, treat as localhost if (int.TryParse(url, out var port)) @@ -211,7 +197,7 @@ private static Uri ParseCliUrl(string url) /// /// /// If the server is not already running and the client is configured to spawn one (default), it will be started. - /// If connecting to an external server (via CliUrl), only establishes the connection. + /// If connecting to an external runtime (via RuntimeConnection.Uri), only establishes the connection. /// /// /// @@ -238,16 +224,16 @@ async Task StartCoreAsync(CancellationToken ct) try { - if (_optionsHost is not null && _optionsPort is not null) + if (_connection is UriRuntimeConnection uriConn) { - // External server (TCP) + // External runtime _actualPort = _optionsPort; connection = await ConnectToServerAsync(null, _optionsHost, _optionsPort, null, ct); } else { // Child process (stdio or TCP) - var (startedProcess, portOrNull, stderrBuffer) = await StartCliServerAsync(_options, _effectiveConnectionToken, _logger, ct); + var (startedProcess, portOrNull, stderrBuffer) = await StartCliServerAsync(ct); cliProcess = startedProcess; _actualPort = portOrNull; connection = await ConnectToServerAsync(cliProcess, portOrNull is null ? null : "localhost", portOrNull, stderrBuffer, ct); @@ -1290,8 +1276,14 @@ private async Task VerifyProtocolVersionAsync(Connection connection, Cancellatio int? serverVersion; try { + var token = _connection switch + { + TcpRuntimeConnection tcp => tcp.ConnectionToken, + UriRuntimeConnection uri => uri.ConnectionToken, + _ => null, + }; var connectResponse = await InvokeRpcAsync( - connection.Rpc, "connect", [new ConnectRequest { Token = _effectiveConnectionToken }], connection.StderrBuffer, cancellationToken); + connection.Rpc, "connect", [new ConnectRequest { Token = token }], connection.StderrBuffer, cancellationToken); serverVersion = (int)connectResponse.ProtocolVersion; } catch (IOException ex) when (ex.InnerException is RemoteRpcException remoteEx && IsUnsupportedConnectMethod(remoteEx)) @@ -1334,21 +1326,27 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) || string.Equals(ex.Message, "Unhandled method connect", StringComparison.Ordinal); } - private static async Task<(Process Process, int? DetectedLocalhostTcpPort, StringBuilder StderrBuffer)> StartCliServerAsync(CopilotClientOptions options, string? connectionToken, ILogger logger, CancellationToken cancellationToken) + private async Task<(Process Process, int? DetectedLocalhostTcpPort, StringBuilder StderrBuffer)> StartCliServerAsync(CancellationToken cancellationToken) { - // Use explicit path, COPILOT_CLI_PATH env var (from options.Environment or process env), or bundled CLI - no PATH fallback + var options = _options; + var logger = _logger; + var childProcessConnection = (ChildProcessRuntimeConnection)_connection; + var tcpConnection = _connection as TcpRuntimeConnection; + var useStdio = _connection is StdioRuntimeConnection; + + // Use explicit path, COPILOT_CLI_PATH env var (from options.Environment or process env), or bundled runtime - no PATH fallback var envCliPath = options.Environment is not null && options.Environment.TryGetValue("COPILOT_CLI_PATH", out var envValue) ? envValue : System.Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"); - var cliPath = options.CliPath + var cliPath = childProcessConnection.Path ?? envCliPath ?? GetBundledCliPath(out var searchedPath) - ?? throw new InvalidOperationException($"Copilot CLI not found at '{searchedPath}'. Ensure the SDK NuGet package was restored correctly or provide an explicit CliPath."); - var cliPathSource = options.CliPath is not null ? "Options" : envCliPath is not null ? "Environment" : "Bundled"; + ?? throw new InvalidOperationException($"Copilot runtime not found at '{searchedPath}'. Ensure the SDK NuGet package was restored correctly or provide an explicit RuntimeConnection.Stdio(path: ...) / RuntimeConnection.Tcp(path: ...)."); + var cliPathSource = childProcessConnection.Path is not null ? "Options" : envCliPath is not null ? "Environment" : "Bundled"; var args = new List(); - if (options.CliArgs != null) + if (childProcessConnection.Args != null) { - args.AddRange(options.CliArgs); + args.AddRange(childProcessConnection.Args); } args.AddRange(["--headless", "--no-auto-update"]); @@ -1357,13 +1355,13 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) args.AddRange(["--log-level", logLevel.Value]); } - if (options.UseStdio == true) + if (useStdio) { args.Add("--stdio"); } - else if (options.Port > 0) + else if (tcpConnection is { Port: > 0 } tcp) { - args.AddRange(["--port", options.Port.ToString(CultureInfo.InvariantCulture)]); + args.AddRange(["--port", tcp.Port.ToString(CultureInfo.InvariantCulture)]); } // Add auth-related flags @@ -1390,15 +1388,15 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) } var (fileName, processArgs) = ResolveCliCommand(cliPath, args); - var configuredPort = options.UseStdio == true ? (int?)null : options.Port; - LogStartingCopilotCli(logger, cliPath, fileName, cliPathSource, options.UseStdio == true, configuredPort); + var configuredPort = useStdio ? (int?)null : tcpConnection?.Port; + LogStartingCopilotCli(logger, cliPath, fileName, cliPathSource, useStdio, configuredPort); var startInfo = new ProcessStartInfo { FileName = fileName, Arguments = string.Join(" ", processArgs.Select(ProcessArgumentEscaper.Escape)), UseShellExecute = false, - RedirectStandardInput = options.UseStdio == true, + RedirectStandardInput = useStdio, RedirectStandardOutput = true, RedirectStandardError = true, WorkingDirectory = options.WorkingDirectory, @@ -1422,14 +1420,14 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) startInfo.Environment["COPILOT_SDK_AUTH_TOKEN"] = options.GitHubToken; } - if (!string.IsNullOrEmpty(connectionToken)) + if (tcpConnection?.ConnectionToken is { Length: > 0 } token) { - startInfo.Environment["COPILOT_CONNECTION_TOKEN"] = connectionToken; + startInfo.Environment["COPILOT_CONNECTION_TOKEN"] = token; } - if (!string.IsNullOrEmpty(options.CopilotHome)) + if (!string.IsNullOrEmpty(options.BaseDirectory)) { - startInfo.Environment["COPILOT_HOME"] = options.CopilotHome; + startInfo.Environment["COPILOT_HOME"] = options.BaseDirectory; } // Set telemetry environment variables if configured @@ -1475,7 +1473,7 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) }, cancellationToken); var detectedLocalhostTcpPort = (int?)null; - if (options.UseStdio != true) + if (!useStdio) { // Wait for port announcement var portWaitTimestamp = Stopwatch.GetTimestamp(); @@ -1488,7 +1486,7 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) if (line is null) { await stderrReader; - throw CreateCliExitedException("CLI process exited unexpectedly", stderrBuffer); + throw CreateCliExitedException("Runtime process exited unexpectedly", stderrBuffer); } if (logger.IsEnabled(LogLevel.Debug)) @@ -1568,11 +1566,11 @@ private async Task ConnectToServerAsync(Process? cliProcess, string? Stream inputStream, outputStream; NetworkStream? networkStream = null; - if (_options.UseStdio == true) + if (_connection is StdioRuntimeConnection) { if (cliProcess == null) { - throw new InvalidOperationException("CLI process not started"); + throw new InvalidOperationException("Runtime process not started"); } inputStream = cliProcess.StandardOutput.BaseStream; diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index b7004854e..00c4764be 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -106,6 +106,106 @@ internal static class Diagnostics public override string ToString() => Value; } +/// +/// Configures how a connects to the Copilot runtime. +/// Use the factory methods on this class to construct an instance. +/// +public abstract class RuntimeConnection +{ + internal RuntimeConnection() { } + + /// + /// Spawn a runtime child process and communicate over its stdin/stdout. + /// This is the default if no is set. + /// + /// Path to the runtime executable. When null, the bundled runtime is used. + /// Extra command-line arguments to pass to the runtime process. + public static StdioRuntimeConnection Stdio(string? path = null, IList? args = null) + => new() { Path = path, Args = args }; + + /// + /// Spawn a runtime child process that listens on a TCP socket and connect to it. + /// + /// TCP port to listen on. 0 (the default) auto-allocates a free port. + /// If the chosen port is already in use, startup fails. + /// Optional shared secret the SDK sends to the spawned runtime to authenticate the TCP connection. + /// When null, a GUID is generated automatically. + /// Path to the runtime executable. When null, the bundled runtime is used. + /// Extra command-line arguments to pass to the runtime process. + public static TcpRuntimeConnection Tcp(int port = 0, string? connectionToken = null, string? path = null, IList? args = null) + => new() { Port = port, ConnectionToken = connectionToken, Path = path, Args = args }; + + /// + /// Connect to an already-running runtime at a given URI. + /// + /// URL of the runtime to connect to. Accepts "port", "host:port", or a full URL. + /// Optional shared secret to authenticate the connection. + public static UriRuntimeConnection Uri(string url, string? connectionToken = null) + => new() { Url = url, ConnectionToken = connectionToken }; +} + +/// +/// Base for kinds that spawn a runtime child process. +/// +public abstract class ChildProcessRuntimeConnection : RuntimeConnection +{ + internal ChildProcessRuntimeConnection() { } + + /// Path to the runtime executable. When null, the bundled runtime is used. + public string? Path { get; set; } + + /// Extra command-line arguments to pass to the runtime process. + public IList? Args { get; set; } +} + +/// +/// Spawns a runtime child process and communicates over stdin/stdout. Construct via +/// . +/// +public sealed class StdioRuntimeConnection : ChildProcessRuntimeConnection +{ + internal StdioRuntimeConnection() { } +} + +/// +/// Spawns a runtime child process listening on a TCP socket. Construct via +/// . +/// +public sealed class TcpRuntimeConnection : ChildProcessRuntimeConnection +{ + internal TcpRuntimeConnection() { } + + /// + /// TCP port to listen on. 0 (the default) auto-allocates a free port. + /// If the chosen port is already in use, startup fails. + /// + public int Port { get; set; } + + /// + /// Optional shared secret the SDK sends to the spawned runtime to authenticate + /// the TCP connection. When null, a GUID is generated automatically. + /// + public string? ConnectionToken { get; set; } +} + +/// +/// Connects to an already-running runtime at the specified URL. Construct via +/// . +/// +public sealed class UriRuntimeConnection : RuntimeConnection +{ + internal UriRuntimeConnection() { } + + /// + /// URL of the runtime to connect to. Accepts "port", "host:port", + /// or a full URL. + /// + public required string Url { get; set; } + + /// Optional shared secret to authenticate the connection. + public string? ConnectionToken { get; set; } +} + /// /// Configuration options for creating a instance. /// @@ -124,61 +224,41 @@ private CopilotClientOptions(CopilotClientOptions? other) { if (other is null) return; - CliArgs = (string[]?)other.CliArgs?.Clone(); - CliPath = other.CliPath; - CliUrl = other.CliUrl; + Connection = other.Connection; WorkingDirectory = other.WorkingDirectory; - CopilotHome = other.CopilotHome; + BaseDirectory = other.BaseDirectory; Environment = other.Environment; GitHubToken = other.GitHubToken; Logger = other.Logger; LogLevel = other.LogLevel; - Port = other.Port; Telemetry = other.Telemetry; UseLoggedInUser = other.UseLoggedInUser; - UseStdio = other.UseStdio; OnListModels = other.OnListModels; SessionFs = other.SessionFs; SessionIdleTimeoutSeconds = other.SessionIdleTimeoutSeconds; - TcpConnectionToken = other.TcpConnectionToken; EnableRemoteSessions = other.EnableRemoteSessions; } /// - /// Path to the Copilot CLI executable. If not specified, uses the bundled CLI from the SDK. - /// - public string? CliPath { get; set; } - /// - /// Additional command-line arguments to pass to the CLI process. + /// How to connect to the runtime. When null, the default is + /// with the bundled runtime. /// - public string[]? CliArgs { get; set; } + public RuntimeConnection? Connection { get; set; } + /// - /// Working directory for the CLI process. + /// Working directory for the runtime process. /// public string? WorkingDirectory { get; set; } + /// /// Base directory for Copilot data (session state, config, etc.). - /// Sets the COPILOT_HOME environment variable on the spawned CLI process. - /// When , the CLI defaults to ~/.copilot. - /// This option is only used when the SDK spawns the CLI process; it is ignored - /// when connecting to an external server via . - /// - public string? CopilotHome { get; set; } - /// - /// Port number for the CLI server when not using stdio transport. + /// Sets the COPILOT_HOME environment variable on the spawned runtime. + /// When , the runtime defaults to ~/.copilot. + /// Ignored when connecting to an existing runtime via + /// . /// - public int Port { get; set; } - /// - /// Whether to use stdio transport for communication with the CLI server. - /// Defaults to true when neither nor - /// switches the client into TCP mode. Setting this to true is mutually - /// exclusive with . - /// - public bool? UseStdio { get; set; } - /// - /// URL of an existing CLI server to connect to instead of starting a new one. - /// - public string? CliUrl { get; set; } + public string? BaseDirectory { get; set; } + /// /// Log level for the Copilot runtime. Use the well-known values on /// (, @@ -188,25 +268,23 @@ private CopilotClientOptions(CopilotClientOptions? other) /// log level is used. /// public CopilotLogLevel? LogLevel { get; set; } - /// - /// Environment variables to pass to the CLI process. - /// + + /// Environment variables to pass to the runtime process. public IReadOnlyDictionary? Environment { get; set; } - /// - /// Logger instance for SDK diagnostic output. - /// + + /// Logger instance for SDK diagnostic output. public ILogger? Logger { get; set; } /// /// GitHub token to use for authentication. - /// When provided, the token is passed to the CLI server via environment variable. + /// When provided, the token is passed to the runtime via environment variable. /// This takes priority over other authentication methods. /// public string? GitHubToken { get; set; } /// /// Whether to use the logged-in user for authentication. - /// When true, the CLI server will attempt to use stored OAuth tokens or gh CLI auth. + /// When true, the runtime will attempt to use stored OAuth tokens or gh CLI auth. /// When false, only explicit tokens (GitHubToken or environment variables) are used. /// Default: true (but defaults to false when GitHubToken is provided). /// @@ -215,7 +293,7 @@ private CopilotClientOptions(CopilotClientOptions? other) /// /// Custom handler for listing available models. /// When provided, ListModelsAsync() calls this handler instead of - /// querying the CLI server. Useful in BYOK mode to return models + /// querying the runtime. Useful in BYOK mode to return models /// available from your custom provider. /// public Func>>? OnListModels { get; set; } @@ -229,8 +307,8 @@ private CopilotClientOptions(CopilotClientOptions? other) public SessionFsConfig? SessionFs { get; set; } /// - /// OpenTelemetry configuration for the CLI server. - /// When set to a non- instance, the CLI server is started with OpenTelemetry instrumentation enabled. + /// OpenTelemetry configuration for the runtime. + /// When set to a non- instance, the runtime is started with OpenTelemetry instrumentation enabled. /// public TelemetryConfig? Telemetry { get; set; } @@ -238,24 +316,17 @@ private CopilotClientOptions(CopilotClientOptions? other) /// Server-wide idle timeout for sessions in seconds. /// Sessions without activity for this duration are automatically cleaned up. /// Set to 0 or leave as to disable (sessions live indefinitely). - /// This option is only used when the SDK spawns the CLI process; it is ignored - /// when connecting to an external server via . + /// This option is only used when the SDK spawns the runtime; it is ignored + /// when connecting to an external runtime via . /// public int? SessionIdleTimeoutSeconds { get; set; } - /// - /// Connection token for the headless CLI server (TCP only). When the SDK spawns its own - /// CLI in TCP mode and this is omitted, a GUID is generated automatically so the loopback - /// listener is safe by default. Cannot be combined with = true. - /// - public string? TcpConnectionToken { get; set; } - /// /// Enable remote session support (Mission Control integration). /// When true, sessions in a GitHub repository working directory are /// accessible from GitHub web and mobile. - /// This option is only used when the SDK spawns the CLI process; it is ignored - /// when connecting to an external server via . + /// This option is only used when the SDK spawns the runtime; it is ignored + /// when connecting to an external runtime via . /// public bool EnableRemoteSessions { get; set; } @@ -268,10 +339,7 @@ private CopilotClientOptions(CopilotClientOptions? other) /// Other reference-type properties (for example delegates and the logger) are not /// deep-cloned; the original and the clone will share those objects. /// - public CopilotClientOptions Clone() - { - return new(this); - } + public CopilotClientOptions Clone() => new(this); } /// diff --git a/dotnet/test/ConnectionTokenTests.cs b/dotnet/test/ConnectionTokenTests.cs index dc6f115ba..581ea655e 100644 --- a/dotnet/test/ConnectionTokenTests.cs +++ b/dotnet/test/ConnectionTokenTests.cs @@ -22,14 +22,11 @@ public class ConnectionTokenTestFixture : IAsyncLifetime public async Task InitializeAsync() { Ctx = await E2ETestContext.CreateAsync(); - GoodClient = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions - { - TcpConnectionToken = Token, - }); + GoodClient = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: Token) }); await GoodClient.StartAsync(); - Port = GoodClient.ActualPort - ?? throw new InvalidOperationException("GoodClient is not using TCP mode; ActualPort is null"); + Port = GoodClient.RuntimePort + ?? throw new InvalidOperationException("GoodClient is not using TCP mode; RuntimePort is null"); } public async Task DisposeAsync() @@ -62,11 +59,7 @@ public async Task Connects_With_The_Matching_Token() [Fact] public async Task Rejects_A_Wrong_Token() { - var wrongClient = new CopilotClient(new CopilotClientOptions - { - CliUrl = $"localhost:{_fixture.Port}", - TcpConnectionToken = "wrong", - }); + var wrongClient = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri($"localhost:{_fixture.Port}", connectionToken: "wrong") }); try { @@ -83,10 +76,7 @@ public async Task Rejects_A_Wrong_Token() [Fact] public async Task Rejects_A_Missing_Token_When_One_Is_Required() { - var noTokenClient = new CopilotClient(new CopilotClientOptions - { - CliUrl = $"localhost:{_fixture.Port}", - }); + var noTokenClient = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri($"localhost:{_fixture.Port}") }); try { diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs index a64f4d59e..5d8eec8e4 100644 --- a/dotnet/test/E2E/ClientE2ETests.cs +++ b/dotnet/test/E2E/ClientE2ETests.cs @@ -16,7 +16,7 @@ public class ClientE2ETests [InlineData(false)] // TCP transport public async Task Should_Start_And_Connect_To_Server(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); try { @@ -38,7 +38,7 @@ public async Task Should_Start_And_Connect_To_Server(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_Force_Stop_Without_Cleanup(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll }); await client.ForceStopAsync(); @@ -49,7 +49,7 @@ public async Task Should_Force_Stop_Without_Cleanup(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_Get_Status_With_Version_And_Protocol_Info(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); try { @@ -73,7 +73,7 @@ public async Task Should_Get_Status_With_Version_And_Protocol_Info(bool useStdio [InlineData(false)] // TCP transport public async Task Should_Get_Auth_Status(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); try { @@ -100,7 +100,7 @@ public async Task Should_Get_Auth_Status(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_List_Models_When_Authenticated(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); try { @@ -138,7 +138,7 @@ public async Task Should_List_Models_When_Authenticated(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_Not_Throw_When_Disposing_Session_After_Stopping_Client(bool useStdio) { - await using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); await using var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll }); await client.StopAsync(); @@ -151,8 +151,9 @@ public async Task Should_Report_Error_With_Stderr_When_CLI_Fails_To_Start(bool u { var client = new CopilotClient(new CopilotClientOptions { - CliArgs = ["--nonexistent-flag-for-testing"], - UseStdio = useStdio + Connection = useStdio + ? RuntimeConnection.Stdio(args: ["--nonexistent-flag-for-testing"]) + : RuntimeConnection.Tcp(args: ["--nonexistent-flag-for-testing"]) }); var ex = await Assert.ThrowsAsync(() => client.StartAsync()); @@ -179,7 +180,7 @@ public async Task Should_Report_Error_With_Stderr_When_CLI_Fails_To_Start(bool u [InlineData(false)] // TCP transport public async Task Should_Allow_CreateSession_Called_Without_PermissionHandler(bool useStdio) { - await using var client = new CopilotClient(new CopilotClientOptions { UseStdio = useStdio }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); await using var session = await client.CreateSessionAsync(new SessionConfig()); Assert.NotNull(session.SessionId); @@ -193,17 +194,16 @@ public async Task Should_Allow_ResumeSession_Called_Without_PermissionHandler() await using var ctx = await E2ETestContext.CreateAsync(); await using var client = ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { - TcpConnectionToken = connectionToken, + Connection = RuntimeConnection.Tcp(connectionToken: connectionToken), }); await using var originalSession = await client.CreateSessionAsync(new SessionConfig()); - var port = client.ActualPort + var port = client.RuntimePort ?? throw new InvalidOperationException("Client must be using TCP transport to support multi-client resume."); await using var resumeClient = ctx.CreateClient(options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", - TcpConnectionToken = connectionToken, + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: connectionToken), }); await using var resumedSession = await resumeClient.ResumeSessionAsync(originalSession.SessionId, new()); @@ -232,7 +232,7 @@ public async Task ListModels_WithCustomHandler_CallsHandler(bool useStdio) var callCount = 0; await using var client = new CopilotClient(new CopilotClientOptions { - UseStdio = useStdio, + Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp(), OnListModels = (ct) => { callCount++; @@ -269,7 +269,7 @@ public async Task ListModels_WithCustomHandler_CachesResults(bool useStdio) var callCount = 0; await using var client = new CopilotClient(new CopilotClientOptions { - UseStdio = useStdio, + Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp(), OnListModels = (ct) => { callCount++; @@ -305,7 +305,7 @@ public async Task ListModels_WithCustomHandler_WorksWithoutStart(bool useStdio) var callCount = 0; await using var client = new CopilotClient(new CopilotClientOptions { - UseStdio = useStdio, + Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp(), OnListModels = (ct) => { callCount++; diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index 4ca22f62f..3906b1d5e 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -21,13 +21,10 @@ public async Task Should_Listen_On_Configured_Tcp_Port() var port = GetAvailableTcpPort(); await using var client = Ctx.CreateClient( useStdio: false, - options: new CopilotClientOptions - { - Port = port, - }); + options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(port: port) }); await client.StartAsync(); - Assert.Equal(port, client.ActualPort); + Assert.Equal(port, client.RuntimePort); var response = await client.PingAsync("fixed-port"); Assert.Equal("pong: fixed-port", response.Message); @@ -73,9 +70,8 @@ public async Task Should_Propagate_Process_Options_To_Spawned_Cli() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - CliPath = cliPath, - CliArgs = ["--capture-file", capturePath], - CopilotHome = copilotHomeFromOption, + Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), + BaseDirectory = copilotHomeFromOption, Environment = clientEnv, GitHubToken = "process-option-token", LogLevel = CopilotLogLevel.Debug, @@ -136,8 +132,7 @@ public async Task Should_Forward_EnableSessionTelemetry_In_Wire_Request() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - CliPath = cliPath, - CliArgs = ["--capture-file", capturePath], + Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -164,8 +159,7 @@ public async Task Should_Omit_EnableSessionTelemetry_When_Not_Set() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - CliPath = cliPath, - CliArgs = ["--capture-file", capturePath], + Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -191,8 +185,7 @@ public async Task Should_Propagate_Activity_TraceContext_To_Session_Create_And_S await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - CliPath = cliPath, - CliArgs = ["--capture-file", capturePath], + Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -237,7 +230,7 @@ public async Task ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup() useStdio: false, options: new CopilotClientOptions { - CliPath = cliPath, + Connection = RuntimeConnection.Stdio(path: cliPath), UseLoggedInUser = false, }); @@ -259,8 +252,7 @@ public async Task StartAsync_Cleans_Up_Tcp_Cli_Process_When_Connect_Fails() useStdio: false, options: new CopilotClientOptions { - CliPath = cliPath, - CliArgs = ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)], + Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)]), UseLoggedInUser = false, }); @@ -279,8 +271,7 @@ public async Task Should_Propagate_Activity_TraceContext_To_Session_Resume() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - CliPath = cliPath, - CliArgs = ["--capture-file", capturePath], + Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -348,28 +339,20 @@ public void Should_Allow_Explicit_UseLoggedInUser_True_With_GitHubToken() } [Fact] - public void Should_Throw_When_GitHubToken_Used_With_CliUrl() + public void Should_Throw_When_GitHubToken_Used_With_UriConnection() { Assert.Throws(() => { - _ = new CopilotClient(new CopilotClientOptions - { - CliUrl = "localhost:8080", - GitHubToken = "gho_test_token" - }); + _ = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri("localhost:8080"), GitHubToken = "gho_test_token" }); }); } [Fact] - public void Should_Throw_When_UseLoggedInUser_Used_With_CliUrl() + public void Should_Throw_When_UseLoggedInUser_Used_With_UriConnection() { Assert.Throws(() => { - _ = new CopilotClient(new CopilotClientOptions - { - CliUrl = "localhost:8080", - UseLoggedInUser = false - }); + _ = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri("localhost:8080"), UseLoggedInUser = false }); }); } diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index ae4233031..98cc56e4f 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -24,7 +24,7 @@ public async Task InitializeAsync() Ctx = await E2ETestContext.CreateAsync(); Client1 = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { - TcpConnectionToken = SharedToken, + Connection = RuntimeConnection.Tcp(connectionToken: SharedToken), }, persistent: true); } @@ -65,13 +65,12 @@ public async Task InitializeAsync() }); await initSession.DisposeAsync(); - var port = Client1.ActualPort - ?? throw new InvalidOperationException("Client1 is not using TCP mode; ActualPort is null"); + var port = Client1.RuntimePort + ?? throw new InvalidOperationException("Client1 is not using TCP mode; RuntimePort is null"); _client2 = Ctx.CreateClient(options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", - TcpConnectionToken = MultiClientCommandsElicitationFixture.SharedToken, + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientCommandsElicitationFixture.SharedToken), }); } @@ -215,12 +214,11 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec }); // Use a dedicated client (client3) so we can stop it without affecting client2 - var port = Client1.ActualPort - ?? throw new InvalidOperationException("Client1 ActualPort is null"); + var port = Client1.RuntimePort + ?? throw new InvalidOperationException("Client1 RuntimePort is null"); _client3 = Ctx.CreateClient(options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", - TcpConnectionToken = MultiClientCommandsElicitationFixture.SharedToken, + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientCommandsElicitationFixture.SharedToken), }); // Client3 joins WITH elicitation handler diff --git a/dotnet/test/E2E/MultiClientE2ETests.cs b/dotnet/test/E2E/MultiClientE2ETests.cs index 70a0e56d1..463542205 100644 --- a/dotnet/test/E2E/MultiClientE2ETests.cs +++ b/dotnet/test/E2E/MultiClientE2ETests.cs @@ -26,7 +26,7 @@ public async Task InitializeAsync() Ctx = await E2ETestContext.CreateAsync(); Client1 = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { - TcpConnectionToken = SharedToken, + Connection = RuntimeConnection.Tcp(connectionToken: SharedToken), }, persistent: true); } @@ -63,13 +63,12 @@ public async Task InitializeAsync() }); await initSession.DisposeAsync(); - var port = Client1.ActualPort - ?? throw new InvalidOperationException("Client1 is not using TCP mode; ActualPort is null"); + var port = Client1.RuntimePort + ?? throw new InvalidOperationException("Client1 is not using TCP mode; RuntimePort is null"); _client2 = Ctx.CreateClient(options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", - TcpConnectionToken = MultiClientTestFixture.SharedToken, + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientTestFixture.SharedToken), }); } @@ -331,11 +330,10 @@ public async Task Disconnecting_Client_Removes_Its_Tools() await Client2.ForceStopAsync(); // Recreate client2 for cleanup - var port = Client1.ActualPort!.Value; + var port = Client1.RuntimePort!.Value; _client2 = Ctx.CreateClient(options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", - TcpConnectionToken = MultiClientTestFixture.SharedToken, + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientTestFixture.SharedToken), }); // Now only stable_tool should be available diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index 693b042fb..b0e3e9b37 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -25,11 +25,11 @@ public async Task Should_Continue_Pending_Permission_Request_After_Resume() var releaseOriginalPermission = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var resumedToolInvoked = false; - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = SharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(ResumePermissionTool, "resume_permission_tool")], @@ -56,7 +56,7 @@ await session1.SendAsync(new MessageOptions await suspendedClient.ForceStopAsync(); - await using var resumedTcpClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + await using var resumedTcpClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedTcpClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -108,11 +108,11 @@ public async Task Should_Continue_Pending_External_Tool_Request_After_Resume() var originalToolStarted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var releaseOriginalTool = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = SharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(BlockingExternalTool, "resume_external_tool")], @@ -133,7 +133,7 @@ await session1.SendAsync(new MessageOptions Assert.Equal("beta", await originalToolStarted.Task.WaitAsync(PendingWorkTimeout)); await suspendedClient.ForceStopAsync(); - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -172,11 +172,11 @@ public async Task Should_Keep_Pending_External_Tool_Handleable_On_Warm_Resume_Wh var releaseOriginalTool = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var invocationCount = 0; - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = SharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(BlockingExternalTool, "resume_external_tool")], @@ -198,7 +198,7 @@ await session1.SendAsync(new MessageOptions await suspendedClient.ForceStopAsync(); - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = false, @@ -243,11 +243,11 @@ public async Task Should_Continue_Parallel_Pending_External_Tool_Requests_After_ var releaseOriginalToolA = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var releaseOriginalToolB = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = SharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = @@ -277,7 +277,7 @@ await Task.WhenAll( await suspendedClient.ForceStopAsync(); - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -322,12 +322,12 @@ async Task BlockingToolB([Description("Value to look up")] string value) [Fact] public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() { - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = SharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); string sessionId; - await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken })) + await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) })) { var firstSession = await firstClient.CreateSessionAsync(new SessionConfig { @@ -341,7 +341,7 @@ public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() await firstSession.DisposeAsync(); } - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var resumedSession = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -360,12 +360,12 @@ public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() [Fact] public async Task Should_Report_ContinuePendingWork_True_In_Resume_Event() { - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = SharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); string sessionId; - await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken })) + await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) })) { var firstSession = await firstClient.CreateSessionAsync(new SessionConfig { @@ -382,7 +382,7 @@ public async Task Should_Report_ContinuePendingWork_True_In_Resume_Event() await firstSession.DisposeAsync(); } - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = SharedToken }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); var resumedSession = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -445,7 +445,7 @@ private static async Task> WaitFo private static string GetCliUrl(CopilotClient client) { - var port = client.ActualPort + var port = client.RuntimePort ?? throw new InvalidOperationException("Expected the test server to be listening on a TCP port."); return $"localhost:{port}"; } diff --git a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs index 4d4388b22..ff134f50f 100644 --- a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs +++ b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs @@ -57,7 +57,7 @@ private CopilotClient CreateExtensionsClient() { return Ctx.CreateClient(options: new CopilotClientOptions { - CliArgs = ["--yolo"], + Connection = RuntimeConnection.Tcp(args: ["--yolo"]), Environment = ExtensionsEnabledEnvironment(), }); } diff --git a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs index 03cab27de..2116eedd1 100644 --- a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs @@ -102,7 +102,7 @@ public async Task Should_List_Extensions() // preventing breakage from new gates (e.g., extension-permission-access). await using var yoloClient = Ctx.CreateClient(options: new CopilotClientOptions { - CliArgs = ["--yolo"], + Connection = RuntimeConnection.Tcp(args: ["--yolo"]), }); await using var session = await yoloClient.CreateSessionAsync(new SessionConfig { @@ -188,7 +188,7 @@ public async Task Should_Report_Error_When_Extensions_Are_Not_Available() // preventing breakage from new gates (e.g., extension-permission-access). await using var yoloClient = Ctx.CreateClient(options: new CopilotClientOptions { - CliArgs = ["--yolo"], + Connection = RuntimeConnection.Tcp(args: ["--yolo"]), }); await using var session = await yoloClient.CreateSessionAsync(new SessionConfig { diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index acc3fd640..70373b925 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -103,17 +103,16 @@ public async Task Should_Reject_SetProvider_When_Sessions_Already_Exist() CreateSessionFsProvider = createSessionFsHandler, }); - var port = client1.ActualPort - ?? throw new InvalidOperationException("Client1 is not using TCP mode; ActualPort is null"); + var port = client1.RuntimePort + ?? throw new InvalidOperationException("Client1 is not using TCP mode; RuntimePort is null"); var client2 = Ctx.CreateClient( useStdio: false, options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", LogLevel = CopilotLogLevel.Error, SessionFs = SessionFsConfig, - TcpConnectionToken = "session-fs-shared-token", + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: "session-fs-shared-token"), }); try @@ -463,7 +462,7 @@ private CopilotClient CreateSessionFsClient(string providerRoot, bool useStdio = options: new CopilotClientOptions { SessionFs = SessionFsConfig, - TcpConnectionToken = tcpConnectionToken, + Connection = RuntimeConnection.Tcp(connectionToken: tcpConnectionToken), }); } diff --git a/dotnet/test/E2E/SuspendE2ETests.cs b/dotnet/test/E2E/SuspendE2ETests.cs index 92ea9be50..1f905a5f1 100644 --- a/dotnet/test/E2E/SuspendE2ETests.cs +++ b/dotnet/test/E2E/SuspendE2ETests.cs @@ -50,12 +50,12 @@ public async Task Should_Suspend_Idle_Session_Without_Throwing() public async Task Should_Allow_Resume_And_Continue_Conversation_After_Suspend() { const string sharedToken = "suspend-shared-token"; - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { TcpConnectionToken = sharedToken }); + await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: sharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); string sessionId; - await using (var client1 = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = sharedToken })) + await using (var client1 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: sharedToken) })) { var session1 = await client1.CreateSessionAsync(new SessionConfig { @@ -76,7 +76,7 @@ await session1.SendAndWaitAsync(new MessageOptions // A different client should be able to pick the session back up. The previous // turn was completed before suspend, so there is no pending work to continue. - await using var client2 = Ctx.CreateClient(options: new CopilotClientOptions { CliUrl = cliUrl, TcpConnectionToken = sharedToken }); + await using var client2 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: sharedToken) }); var session2 = await client2.ResumeSessionAsync(sessionId, new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, @@ -219,7 +219,7 @@ async Task BlockingTool([Description("Value to look up")] string value) private static string GetCliUrl(CopilotClient client) { - var port = client.ActualPort + var port = client.RuntimePort ?? throw new InvalidOperationException("Expected the test server to be listening on a TCP port."); return $"localhost:{port}"; } diff --git a/dotnet/test/Harness/E2ETestBase.cs b/dotnet/test/Harness/E2ETestBase.cs index ca5d2b816..b11efa3d1 100644 --- a/dotnet/test/Harness/E2ETestBase.cs +++ b/dotnet/test/Harness/E2ETestBase.cs @@ -88,13 +88,12 @@ protected async Task ResumeSessionAsync(string sessionId, Resume config.OnPermissionRequest ??= PermissionHandler.ApproveAll; await Client.StartAsync(); - var port = Client.ActualPort + var port = Client.RuntimePort ?? throw new InvalidOperationException("The shared E2E client must use TCP transport to support multi-client resume."); var client = Ctx.CreateClient(options: new CopilotClientOptions { - CliUrl = $"localhost:{port}", - TcpConnectionToken = E2ETestFixture.SharedTcpConnectionToken, + Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: E2ETestFixture.SharedTcpConnectionToken), }); return await client.ResumeSessionAsync(sessionId, config); } diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index 5c69e4320..34f4a9a4c 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -214,17 +214,29 @@ public CopilotClient CreateClient( options.WorkingDirectory ??= WorkDir; options.Environment ??= GetEnvironment(); - options.UseStdio = useStdio; options.Logger ??= Logger; - if (string.IsNullOrEmpty(options.CliUrl)) + // Build the connection. If the caller supplied one, just ensure the runtime path is set; + // otherwise default to Tcp with bundled CLI path (matches the previous "useStdio: false, + // CliPath = bundled" behavior). + var cliPath = GetCliPath(_repoRoot); + switch (options.Connection) { - options.CliPath ??= GetCliPath(_repoRoot); + case null: + options.Connection = useStdio == true + ? RuntimeConnection.Stdio(path: cliPath) + : RuntimeConnection.Tcp(path: cliPath); + break; + case ChildProcessRuntimeConnection child when child.Path is null: + child.Path = cliPath; + break; } + // Auto-inject auth token unless connecting to an existing runtime via URI. + var isExistingRuntime = options.Connection is UriRuntimeConnection; if (autoInjectGitHubToken && string.IsNullOrEmpty(options.GitHubToken) - && string.IsNullOrEmpty(options.CliUrl)) + && !isExistingRuntime) { options.GitHubToken = DefaultGitHubToken; } diff --git a/dotnet/test/Harness/E2ETestFixture.cs b/dotnet/test/Harness/E2ETestFixture.cs index a53e4bd32..5e1e090e7 100644 --- a/dotnet/test/Harness/E2ETestFixture.cs +++ b/dotnet/test/Harness/E2ETestFixture.cs @@ -19,7 +19,7 @@ public async Task InitializeAsync() Ctx = await E2ETestContext.CreateAsync(); Client = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { - TcpConnectionToken = SharedTcpConnectionToken, + Connection = RuntimeConnection.Tcp(connectionToken: SharedTcpConnectionToken), }, persistent: true); } diff --git a/dotnet/test/Unit/ClientSessionLifetimeTests.cs b/dotnet/test/Unit/ClientSessionLifetimeTests.cs index cf59b0fbb..ba8fb7d8d 100644 --- a/dotnet/test/Unit/ClientSessionLifetimeTests.cs +++ b/dotnet/test/Unit/ClientSessionLifetimeTests.cs @@ -19,7 +19,7 @@ public sealed class ClientSessionLifetimeTests public async Task Dropped_Session_Remains_Rooted_By_Client() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); var weakSession = await CreateDroppedSessionAsync(client); @@ -36,7 +36,7 @@ public async Task Dropped_Session_Remains_Rooted_By_Client() public async Task Disposed_Session_Is_Removed_From_Client() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); var session = await client.CreateSessionAsync(new SessionConfig { @@ -54,7 +54,7 @@ public async Task Disposing_Session_Remains_Rooted_Until_Destroy_Completes() { await using var server = await FakeCopilotServer.StartAsync(); server.DelayDestroy(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); var session = await client.CreateSessionAsync(new SessionConfig { @@ -77,7 +77,7 @@ public async Task Disposing_Session_Remains_Rooted_Until_Destroy_Completes() public async Task StopAsync_Removes_Rooted_Sessions() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); _ = await client.CreateSessionAsync(new SessionConfig { @@ -95,7 +95,7 @@ public async Task StopAsync_Keeps_Session_Rooted_Until_Destroy_Completes() { await using var server = await FakeCopilotServer.StartAsync(); server.DelayDestroy(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); _ = await client.CreateSessionAsync(new SessionConfig { @@ -118,7 +118,7 @@ public async Task StopAsync_Keeps_Session_Rooted_Until_Destroy_Completes() public async Task ResumeSessionAsync_Throws_When_Same_Client_Already_Tracks_Session() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); var sessionId = "same-session-id"; await using var session = await client.CreateSessionAsync(new SessionConfig @@ -140,7 +140,7 @@ public async Task ResumeSessionAsync_Throws_When_Same_Client_Already_Tracks_Sess public async Task Generated_Session_Rpc_Throws_When_Session_Disposed() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { CliUrl = server.Url }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); var session = await client.CreateSessionAsync(new SessionConfig { diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 29f4241ce..7c175fef5 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -13,53 +13,39 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() { var original = new CopilotClientOptions { - CliPath = "/usr/bin/copilot", - CliArgs = ["--verbose", "--debug"], + Connection = RuntimeConnection.Tcp(port: 8080, connectionToken: "tok", path: "/usr/bin/copilot", args: ["--verbose", "--debug"]), WorkingDirectory = "/home/user", - Port = 8080, - UseStdio = false, - CliUrl = "http://localhost:8080", LogLevel = CopilotLogLevel.Debug, - Environment = new Dictionary { ["KEY"] = "value" }, + Environment = new Dictionary { ["KEY"] = "value" }, GitHubToken = "ghp_test", UseLoggedInUser = false, - CopilotHome = "/custom/copilot/home", + BaseDirectory = "/custom/copilot/home", EnableRemoteSessions = true, SessionIdleTimeoutSeconds = 600, }; var clone = original.Clone(); - Assert.Equal(original.CliPath, clone.CliPath); - Assert.Equal(original.CliArgs, clone.CliArgs); + Assert.Same(original.Connection, clone.Connection); Assert.Equal(original.WorkingDirectory, clone.WorkingDirectory); - Assert.Equal(original.Port, clone.Port); - Assert.Equal(original.UseStdio, clone.UseStdio); - Assert.Equal(original.CliUrl, clone.CliUrl); Assert.Equal(original.LogLevel, clone.LogLevel); Assert.Equal(original.Environment, clone.Environment); Assert.Equal(original.GitHubToken, clone.GitHubToken); Assert.Equal(original.UseLoggedInUser, clone.UseLoggedInUser); - Assert.Equal(original.CopilotHome, clone.CopilotHome); + Assert.Equal(original.BaseDirectory, clone.BaseDirectory); Assert.Equal(original.EnableRemoteSessions, clone.EnableRemoteSessions); Assert.Equal(original.SessionIdleTimeoutSeconds, clone.SessionIdleTimeoutSeconds); } [Fact] - public void CopilotClientOptions_Clone_CollectionsAreIndependent() + public void CopilotClientOptions_Clone_ConnectionIsShared() { - var original = new CopilotClientOptions - { - CliArgs = ["--verbose"], - }; + var connection = RuntimeConnection.Stdio(); + var original = new CopilotClientOptions { Connection = connection }; var clone = original.Clone(); - // Mutate clone array - clone.CliArgs![0] = "--quiet"; - - // Original is unaffected - Assert.Equal("--verbose", original.CliArgs![0]); + Assert.Same(connection, clone.Connection); } [Fact] From 7ca216e9823a042955c459dde15317079ab9a57c Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 16:04:24 +0100 Subject: [PATCH 16/40] README: update Custom Permission Handler section for Phase 6 delegate removal Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/README.md b/dotnet/README.md index 159f5e7e2..9330abf4c 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -749,7 +749,7 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Custom Permission Handler -Provide your own `PermissionRequestHandler` delegate to inspect each request and apply custom logic: +Provide your own permission handler (`Func>`) to inspect each request and apply custom logic: ```csharp var session = await client.CreateSessionAsync(new SessionConfig From aee238441a8ca306e2c6e877fe12ca95965a4e82 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 17:19:34 +0100 Subject: [PATCH 17/40] Fix snapshot capture locally --- dotnet/test/Harness/E2ETestContext.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index 34f4a9a4c..afd031bbc 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -195,15 +195,19 @@ public IReadOnlyDictionary GetEnvironment() env["GH_ENTERPRISE_TOKEN"] = ""; env["GITHUB_ENTERPRISE_TOKEN"] = ""; } - if (Environment.GetEnvironmentVariable("GITHUB_ACTIONS") == "true") - { - env["GH_TOKEN"] = DefaultGitHubToken; - env["GITHUB_TOKEN"] = DefaultGitHubToken; - } + + env["GITHUB_TOKEN"] = env["GH_TOKEN"] = ""; return env!; } + private static string? GetEffectiveGitHubTokenForTests() + { + return Environment.GetEnvironmentVariable("GITHUB_ACTIONS") == "true" + ? DefaultGitHubToken + : Environment.GetEnvironmentVariable("GITHUB_TOKEN"); + } + public CopilotClient CreateClient( bool? useStdio = null, CopilotClientOptions? options = null, @@ -238,7 +242,7 @@ public CopilotClient CreateClient( && string.IsNullOrEmpty(options.GitHubToken) && !isExistingRuntime) { - options.GitHubToken = DefaultGitHubToken; + options.GitHubToken = GetEffectiveGitHubTokenForTests(); } var client = new CopilotClient(options); From 23826211dd1e64635f98a761399cbe2a9b5a0069 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 17:37:23 +0100 Subject: [PATCH 18/40] Fix MCP config serialization --- dotnet/src/Types.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 00c4764be..9dfedb6e1 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -1908,6 +1908,7 @@ private protected McpServerConfig() { } /// Optional timeout in milliseconds for tool calls to this server. /// [JsonPropertyName("timeout")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public int? Timeout { get; set; } } @@ -1936,12 +1937,14 @@ public sealed class McpStdioServerConfig : McpServerConfig /// Environment variables to pass to the server. /// [JsonPropertyName("env")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IDictionary? Env { get; set; } /// /// Working directory for the server process. /// [JsonPropertyName("cwd")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? WorkingDirectory { get; set; } } @@ -1964,24 +1967,28 @@ public sealed class McpHttpServerConfig : McpServerConfig /// Optional HTTP headers to include in requests. /// [JsonPropertyName("headers")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IDictionary? Headers { get; set; } /// /// Optional OAuth client ID for the remote server. /// [JsonPropertyName("oauthClientId")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? OauthClientId { get; set; } /// /// Whether this is a public OAuth client. /// [JsonPropertyName("oauthPublicClient")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? OauthPublicClient { get; set; } /// /// Optional OAuth grant type for the remote server. /// [JsonPropertyName("oauthGrantType")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public McpHttpServerConfigOauthGrantType? OauthGrantType { get; set; } } From 48aa42f4c2e7204d0bcc77204924a7240cc70184 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 17:45:40 +0100 Subject: [PATCH 19/40] Revert "Phase 1: codegen falls back to JsonElement instead of object" This reverts commit ff93ad6b720578877104b4caf698fb68cfd807b9. --- dotnet/src/Client.cs | 9 ++- dotnet/src/Generated/Rpc.cs | 26 ++++--- dotnet/src/Generated/SessionEvents.cs | 38 ++++----- dotnet/src/Session.cs | 77 ++++++++++--------- dotnet/src/SessionFsProvider.cs | 22 +----- dotnet/src/Types.cs | 12 +-- .../E2E/InMemorySessionFsSqliteHandler.cs | 4 +- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 9 +-- dotnet/test/E2E/RpcMcpConfigE2ETests.cs | 8 +- .../test/E2E/RpcTasksAndHandlersE2ETests.cs | 3 +- dotnet/test/E2E/SessionFsE2ETests.cs | 2 +- dotnet/test/E2E/ToolResultsE2ETests.cs | 6 +- dotnet/test/TestJsonContext.cs | 16 ---- .../Unit/SessionEventSerializationTests.cs | 2 +- scripts/codegen/csharp.ts | 12 +-- 15 files changed, 111 insertions(+), 135 deletions(-) delete mode 100644 dotnet/test/TestJsonContext.cs diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 56f9a8d15..59a30fbd1 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -1808,7 +1808,7 @@ public async ValueTask OnSystemMessageTransfo public async ValueTask OnToolCallV2(string sessionId, string toolCallId, string toolName, - JsonElement? arguments, + object? arguments, string? traceparent = null, string? tracestate = null) { @@ -1845,8 +1845,13 @@ public async ValueTask OnToolCallV2(string sessionId, } }; - if (arguments is JsonElement incomingJsonArgs) + if (arguments is not null) { + if (arguments is not JsonElement incomingJsonArgs) + { + throw new InvalidOperationException($"Incoming arguments must be a {nameof(JsonElement)}; received {arguments.GetType().Name}"); + } + foreach (var prop in incomingJsonArgs.EnumerateObject()) { aiFunctionArgs[prop.Name] = prop.Value; diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index f60aa7f78..2bd4910a2 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -247,7 +247,7 @@ public sealed class Tool /// JSON Schema for the tool's input parameters. [JsonPropertyName("parameters")] - public IDictionary? Parameters { get; set; } + public IDictionary? Parameters { get; set; } } /// Built-in tools available for the requested model, with their parameters and instructions. @@ -362,7 +362,7 @@ public sealed class McpConfigList { /// All MCP servers from user config, keyed by name. [JsonPropertyName("servers")] - public IDictionary Servers { get => field ??= new Dictionary(); set; } + public IDictionary Servers { get => field ??= new Dictionary(); set; } } /// MCP server name and configuration to add to user configuration. @@ -370,7 +370,7 @@ internal sealed class McpConfigAddRequest { /// MCP server configuration (stdio process or remote HTTP/SSE). [JsonPropertyName("config")] - public JsonElement Config { get; set; } + public object Config { get; set; } = null!; /// Unique name for the MCP server. [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] @@ -385,7 +385,7 @@ internal sealed class McpConfigUpdateRequest { /// MCP server configuration (stdio process or remote HTTP/SSE). [JsonPropertyName("config")] - public JsonElement Config { get; set; } + public object Config { get; set; } = null!; /// Name of the MCP server to update. [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] @@ -3936,7 +3936,7 @@ internal sealed class HandlePendingToolCallRequest /// Tool call result (string or expanded result object). [JsonPropertyName("result")] - public JsonElement? Result { get; set; } + public object? Result { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] @@ -4353,7 +4353,7 @@ public sealed class UIElicitationResponse /// The form values submitted by the user (present when action is 'accept'). [JsonPropertyName("content")] - public IDictionary? Content { get; set; } + public IDictionary? Content { get; set; } } /// JSON Schema describing the form fields to present to the user. @@ -4362,7 +4362,7 @@ public sealed class UIElicitationSchema { /// Form field definitions, keyed by field name. [JsonPropertyName("properties")] - public IDictionary Properties { get => field ??= new Dictionary(); set; } + public IDictionary Properties { get => field ??= new Dictionary(); set; } /// List of required field names. [JsonPropertyName("required")] @@ -7108,7 +7108,7 @@ public sealed class SessionFsSqliteQueryResult /// For SELECT: array of row objects. For others: empty array. [JsonPropertyName("rows")] - public IList> Rows { get => field ??= []; set; } + public IList> Rows { get => field ??= []; set; } /// Number of rows affected (for INSERT/UPDATE/DELETE). [JsonPropertyName("rowsAffected")] @@ -7120,7 +7120,7 @@ public sealed class SessionFsSqliteQueryRequest { /// Optional named bind parameters. [JsonPropertyName("params")] - public IDictionary? Params { get; set; } + public IDictionary? Params { get; set; } /// SQL query to execute. [JsonPropertyName("query")] @@ -10289,9 +10289,10 @@ public async Task ListAsync(CancellationToken cancellationToken = /// Unique name for the MCP server. /// MCP server configuration (stdio process or remote HTTP/SSE). /// The to monitor for cancellation requests. The default is . - public async Task AddAsync(string name, JsonElement config, CancellationToken cancellationToken = default) + public async Task AddAsync(string name, object config, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(config); var request = new McpConfigAddRequest { Name = name, Config = config }; await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.add", [request], cancellationToken); @@ -10301,9 +10302,10 @@ public async Task AddAsync(string name, JsonElement config, CancellationToken ca /// Name of the MCP server to update. /// MCP server configuration (stdio process or remote HTTP/SSE). /// The to monitor for cancellation requests. The default is . - public async Task UpdateAsync(string name, JsonElement config, CancellationToken cancellationToken = default) + public async Task UpdateAsync(string name, object config, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(config); var request = new McpConfigUpdateRequest { Name = name, Config = config }; await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.update", [request], cancellationToken); @@ -11912,7 +11914,7 @@ internal ToolsApi(CopilotSession session) /// Error message if the tool call failed. /// The to monitor for cancellation requests. The default is . /// Indicates whether the external tool call result was handled successfully. - public async Task HandlePendingToolCallAsync(string requestId, JsonElement? result = null, string? error = null, CancellationToken cancellationToken = default) + public async Task HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(requestId); _session.ThrowIfDisposed(); diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index b4b0e7fbd..c5a00b5d6 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -1991,7 +1991,7 @@ public sealed partial class AssistantMessageData /// Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("anthropicAdvisorBlocks")] - public JsonElement[]? AnthropicAdvisorBlocks { get; set; } + public object[]? AnthropicAdvisorBlocks { get; set; } /// Anthropic advisor model ID used for this response, for timeline display on replay. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2260,7 +2260,7 @@ public sealed partial class ToolUserRequestedData /// Arguments for the tool invocation. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public JsonElement? Arguments { get; set; } + public object? Arguments { get; set; } /// Unique identifier for this tool call. [JsonPropertyName("toolCallId")] @@ -2277,7 +2277,7 @@ public sealed partial class ToolExecutionStartData /// Arguments passed to the tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public JsonElement? Arguments { get; set; } + public object? Arguments { get; set; } /// Name of the MCP server hosting this tool, when the tool is an MCP tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2380,7 +2380,7 @@ public sealed partial class ToolExecutionCompleteData /// Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolTelemetry")] - public IDictionary? ToolTelemetry { get; set; } + public IDictionary? ToolTelemetry { get; set; } /// Identifier for the agent loop turn this tool was invoked in, matching the corresponding assistant.turn_start event. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2562,7 +2562,7 @@ public sealed partial class HookStartData /// Input data passed to the hook. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("input")] - public JsonElement? Input { get; set; } + public object? Input { get; set; } } /// Hook invocation completion details including output, success status, and error information. @@ -2584,7 +2584,7 @@ public sealed partial class HookEndData /// Output data produced by the hook. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("output")] - public JsonElement? Output { get; set; } + public object? Output { get; set; } /// Whether the hook completed successfully. [JsonPropertyName("success")] @@ -2757,7 +2757,7 @@ public sealed partial class ElicitationCompletedData /// The submitted form data when action is 'accept'; keys match the requested schema fields. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("content")] - public IDictionary? Content { get; set; } + public IDictionary? Content { get; set; } /// Request ID of the resolved elicitation request; clients should dismiss any UI for this request. [JsonPropertyName("requestId")] @@ -2769,7 +2769,7 @@ public sealed partial class SamplingRequestedData { /// The JSON-RPC request ID from the MCP protocol. [JsonPropertyName("mcpRequestId")] - public required JsonElement McpRequestId { get; set; } + public required object McpRequestId { get; set; } /// Unique identifier for this sampling request; used to respond via session.respondToSampling(). [JsonPropertyName("requestId")] @@ -2830,7 +2830,7 @@ public sealed partial class SessionCustomNotificationData /// Source-defined JSON payload for the custom notification. [JsonPropertyName("payload")] - public required JsonElement Payload { get; set; } + public required object Payload { get; set; } /// Namespace for the custom notification producer. [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] @@ -2855,7 +2855,7 @@ public sealed partial class ExternalToolRequestedData /// Arguments to pass to the external tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public JsonElement? Arguments { get; set; } + public object? Arguments { get; set; } /// Unique identifier for this request; used to respond via session.respondToExternalTool(). [JsonPropertyName("requestId")] @@ -3525,7 +3525,7 @@ public sealed partial class AssistantMessageToolRequest /// Arguments to pass to the tool, format depends on the tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("arguments")] - public JsonElement? Arguments { get; set; } + public object? Arguments { get; set; } /// Resolved intention summary describing what this specific call does. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3983,7 +3983,7 @@ public sealed partial class SystemMessageMetadata /// Template variables used when constructing the prompt. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("variables")] - public IDictionary? Variables { get; set; } + public IDictionary? Variables { get; set; } } /// Schema for the `SystemNotificationAgentCompleted` type. @@ -4289,7 +4289,7 @@ public sealed partial class PermissionRequestMcp : PermissionRequest /// Arguments to pass to the MCP tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public JsonElement? Args { get; set; } + public object? Args { get; set; } /// Whether this MCP tool is read-only (no side effects). [JsonPropertyName("readOnly")] @@ -4391,7 +4391,7 @@ public sealed partial class PermissionRequestCustomTool : PermissionRequest /// Arguments to pass to the custom tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public JsonElement? Args { get; set; } + public object? Args { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4423,7 +4423,7 @@ public sealed partial class PermissionRequestHook : PermissionRequest /// Arguments of the tool call being gated. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolArgs")] - public JsonElement? ToolArgs { get; set; } + public object? ToolArgs { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4606,7 +4606,7 @@ public sealed partial class PermissionPromptRequestMcp : PermissionPromptRequest /// Arguments to pass to the MCP tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public JsonElement? Args { get; set; } + public object? Args { get; set; } /// Name of the MCP server providing the tool. [JsonPropertyName("serverName")] @@ -4704,7 +4704,7 @@ public sealed partial class PermissionPromptRequestCustomTool : PermissionPrompt /// Arguments to pass to the custom tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("args")] - public JsonElement? Args { get; set; } + public object? Args { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4758,7 +4758,7 @@ public sealed partial class PermissionPromptRequestHook : PermissionPromptReques /// Arguments of the tool call being gated. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolArgs")] - public JsonElement? ToolArgs { get; set; } + public object? ToolArgs { get; set; } /// Tool call ID that triggered this permission request. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -5128,7 +5128,7 @@ public sealed partial class ElicitationRequestedSchema { /// Form field definitions, keyed by field name. [JsonPropertyName("properties")] - public required IDictionary Properties { get; set; } + public required IDictionary Properties { get; set; } /// List of required field names. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 5e19baa53..6291b84c8 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -640,7 +640,7 @@ private async Task HandleBroadcastEventAsync(SessionEvent sessionEvent) ? new ElicitationSchema { Type = data.RequestedSchema.Type, - Properties = data.RequestedSchema.Properties.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value), + Properties = data.RequestedSchema.Properties, Required = data.RequestedSchema.Required?.ToList() } : null; @@ -690,7 +690,7 @@ await HandleElicitationRequestAsync( /// /// Executes a tool handler and sends the result back via the HandlePendingToolCall RPC. /// - private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, string toolCallId, JsonElement? arguments, AIFunction tool) + private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, string toolCallId, object? arguments, AIFunction tool) { try { @@ -710,8 +710,13 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, } }; - if (arguments is JsonElement incomingJsonArgs) + if (arguments is not null) { + if (arguments is not JsonElement incomingJsonArgs) + { + throw new InvalidOperationException($"Incoming arguments must be a {nameof(JsonElement)}; received {arguments.GetType().Name}"); + } + foreach (var prop in incomingJsonArgs.EnumerateObject()) { aiFunctionArgs[prop.Name] = prop.Value; @@ -729,10 +734,9 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName, toolName); var toolResultObject = ToolResultObject.ConvertFromInvocationResult(result, tool.JsonSerializerOptions); - var toolResultJson = JsonSerializer.SerializeToElement(toolResultObject, TypesJsonContext.Default.ToolResultObject); var responseRpcTimestamp = Stopwatch.GetTimestamp(); - await Rpc.Tools.HandlePendingToolCallAsync(requestId, toolResultJson, error: null); + await Rpc.Tools.HandlePendingToolCallAsync(requestId, toolResultObject, error: null); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, "CopilotSession.ExecuteToolAndRespondAsync response sent successfully. Elapsed={Elapsed}, SessionId={SessionId}, RequestId={RequestId}, ToolCallId={ToolCallId}, Tool={ToolName}", responseRpcTimestamp, @@ -953,9 +957,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UIElicitationResponse { Action = result.Action, - Content = result.Content?.ToDictionary( - kvp => kvp.Key, - kvp => JsonSerializer.SerializeToElement(kvp.Value, TypesJsonContext.Default.Object)) + Content = result.Content }); LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null, "CopilotSession.HandleElicitationRequestAsync response sent successfully. Elapsed={Elapsed}, SessionId={SessionId}, RequestId={RequestId}", @@ -1007,18 +1009,12 @@ public async Task ElicitAsync(ElicitationParams elicitationPa var schema = new UIElicitationSchema { Type = elicitationParams.RequestedSchema.Type, - Properties = elicitationParams.RequestedSchema.Properties.ToDictionary( - kvp => kvp.Key, - kvp => JsonSerializer.SerializeToElement(kvp.Value, TypesJsonContext.Default.Object)), + Properties = elicitationParams.RequestedSchema.Properties, Required = elicitationParams.RequestedSchema.Required }; var result = await session.Rpc.Ui.ElicitationAsync(elicitationParams.Message, schema, cancellationToken); - return new ElicitationResult - { - Action = result.Action, - Content = result.Content?.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value) - }; + return new ElicitationResult { Action = result.Action, Content = result.Content }; } public async Task ConfirmAsync(string message, CancellationToken cancellationToken) @@ -1030,9 +1026,9 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat var schema = new UIElicitationSchema { Type = "object", - Properties = new Dictionary + Properties = new Dictionary { - ["confirmed"] = JsonDocument.Parse("""{"type":"boolean","default":true}""").RootElement.Clone() + ["confirmed"] = new Dictionary { ["type"] = "boolean", ["default"] = true } }, Required = ["confirmed"] }; @@ -1042,10 +1038,11 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat && result.Content != null && result.Content.TryGetValue("confirmed", out var val)) { - return val.ValueKind switch + return val switch { - JsonValueKind.True => true, - JsonValueKind.False => false, + bool b => b, + JsonElement { ValueKind: JsonValueKind.True } => true, + JsonElement { ValueKind: JsonValueKind.False } => false, _ => false }; } @@ -1060,13 +1057,12 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat session.ThrowIfDisposed(); session.AssertElicitation(); - var enumJson = JsonSerializer.Serialize(options, TypesJsonContext.Default.StringArray); var schema = new UIElicitationSchema { Type = "object", - Properties = new Dictionary + Properties = new Dictionary { - ["selection"] = JsonDocument.Parse($$"""{"type":"string","enum":{{enumJson}}}""").RootElement.Clone() + ["selection"] = new Dictionary { ["type"] = "string", ["enum"] = options } }, Required = ["selection"] }; @@ -1076,7 +1072,12 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat && result.Content != null && result.Content.TryGetValue("selection", out var val)) { - return val.ValueKind == JsonValueKind.String ? val.GetString() : val.ToString(); + return val switch + { + string s => s, + JsonElement { ValueKind: JsonValueKind.String } je => je.GetString(), + _ => val.ToString() + }; } return null; @@ -1088,21 +1089,18 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat session.ThrowIfDisposed(); session.AssertElicitation(); - var fieldNode = new System.Text.Json.Nodes.JsonObject { ["type"] = "string" }; - if (options?.Title != null) fieldNode["title"] = options.Title; - if (options?.Description != null) fieldNode["description"] = options.Description; - if (options?.MinLength != null) fieldNode["minLength"] = options.MinLength; - if (options?.MaxLength != null) fieldNode["maxLength"] = options.MaxLength; - if (options?.Format != null) fieldNode["format"] = options.Format; - if (options?.Default != null) fieldNode["default"] = options.Default; + var field = new Dictionary { ["type"] = "string" }; + if (options?.Title != null) field["title"] = options.Title; + if (options?.Description != null) field["description"] = options.Description; + if (options?.MinLength != null) field["minLength"] = options.MinLength; + if (options?.MaxLength != null) field["maxLength"] = options.MaxLength; + if (options?.Format != null) field["format"] = options.Format; + if (options?.Default != null) field["default"] = options.Default; var schema = new UIElicitationSchema { Type = "object", - Properties = new Dictionary - { - ["value"] = JsonDocument.Parse(fieldNode.ToJsonString()).RootElement.Clone() - }, + Properties = new Dictionary { ["value"] = field }, Required = ["value"] }; @@ -1111,7 +1109,12 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat && result.Content != null && result.Content.TryGetValue("value", out var val)) { - return val.ValueKind == JsonValueKind.String ? val.GetString() : val.ToString(); + return val switch + { + string s => s, + JsonElement { ValueKind: JsonValueKind.String } je => je.GetString(), + _ => val.ToString() + }; } return null; diff --git a/dotnet/src/SessionFsProvider.cs b/dotnet/src/SessionFsProvider.cs index 7ab8bf81b..cfe1d83ef 100644 --- a/dotnet/src/SessionFsProvider.cs +++ b/dotnet/src/SessionFsProvider.cs @@ -3,7 +3,6 @@ *--------------------------------------------------------------------------------------------*/ using GitHub.Copilot.SDK.Rpc; -using System.Text.Json; namespace GitHub.Copilot.SDK; @@ -45,7 +44,7 @@ public interface ISessionFsSqliteProvider Task QueryAsync( SessionFsSqliteQueryType queryType, string query, - IDictionary? bindParams, + IDictionary? bindParams, CancellationToken cancellationToken); /// @@ -288,16 +287,11 @@ async Task ISessionFsHandler.SqliteQueryAsync(Sessio try { - var bindParams = request.Params?.ToDictionary( - kvp => kvp.Key, - kvp => JsonElementToValue(kvp.Value)); - var result = await sqliteProvider.QueryAsync(request.QueryType, request.Query, bindParams, cancellationToken).ConfigureAwait(false); + var result = await sqliteProvider.QueryAsync(request.QueryType, request.Query, request.Params, cancellationToken).ConfigureAwait(false); return new SessionFsSqliteQueryResult { - Rows = result?.Rows?.Select(row => (IDictionary)row.ToDictionary( - kvp => kvp.Key, - kvp => JsonSerializer.SerializeToElement(kvp.Value, TypesJsonContext.Default.Object))).ToList() ?? [], + Rows = result?.Rows ?? [], Columns = result?.Columns ?? [], RowsAffected = result?.RowsAffected ?? 0, LastInsertRowid = result?.LastInsertRowid, @@ -335,14 +329,4 @@ private static SessionFsError ToSessionFsError(Exception ex) : SessionFsErrorCode.UNKNOWN; return new SessionFsError { Code = code, Message = ex.Message }; } - - private static object? JsonElementToValue(JsonElement element) => element.ValueKind switch - { - JsonValueKind.Null => null, - JsonValueKind.True => true, - JsonValueKind.False => false, - JsonValueKind.String => element.GetString(), - JsonValueKind.Number => element.TryGetInt64(out var l) ? l : element.GetDouble(), - _ => element.GetRawText(), - }; } diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 9dfedb6e1..f125abc1a 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -559,7 +559,7 @@ public sealed class ToolResultObject /// Custom telemetry data associated with the tool execution. /// [JsonPropertyName("toolTelemetry")] - public IDictionary? ToolTelemetry { get; set; } + public IDictionary? ToolTelemetry { get; set; } /// /// Converts the result of an invocation into a @@ -671,7 +671,7 @@ public sealed class ToolInvocation /// /// Arguments passed to the tool by the language model. /// - public JsonElement? Arguments { get; set; } + public object? Arguments { get; set; } } /// Describes the kind of a permission request result. @@ -1227,7 +1227,7 @@ public sealed class PreToolUseHookInput /// Arguments that will be passed to the tool. /// [JsonPropertyName("toolArgs")] - public JsonElement? ToolArgs { get; set; } + public object? ToolArgs { get; set; } } /// @@ -1305,13 +1305,13 @@ public sealed class PostToolUseHookInput /// Arguments that were passed to the tool. /// [JsonPropertyName("toolArgs")] - public JsonElement? ToolArgs { get; set; } + public object? ToolArgs { get; set; } /// /// Result returned by the tool execution. /// [JsonPropertyName("toolResult")] - public JsonElement? ToolResult { get; set; } + public object? ToolResult { get; set; } } /// @@ -2994,4 +2994,4 @@ public sealed class SystemMessageTransformRpcResponse [JsonSerializable(typeof(object))] [JsonSerializable(typeof(Dictionary))] [JsonSerializable(typeof(string[]))] -internal partial class TypesJsonContext : JsonSerializerContext; \ No newline at end of file +internal partial class TypesJsonContext : JsonSerializerContext; diff --git a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs index 965cce6b7..5c8831caf 100644 --- a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs +++ b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs @@ -43,7 +43,7 @@ private SqliteConnection GetOrCreateDb() public Task QueryAsync( SessionFsSqliteQueryType queryType, string query, - IDictionary? bindParams, + IDictionary? bindParams, CancellationToken cancellationToken) { sqliteCalls.Add(new SqliteCall(sessionId, queryType.Value, query)); @@ -125,7 +125,7 @@ public Task ExistsAsync(CancellationToken cancellationToken) return Task.FromResult(_db is not null); } - private static void AddParams(SqliteCommand cmd, IDictionary? bindParams) + private static void AddParams(SqliteCommand cmd, IDictionary? bindParams) { if (bindParams is null) return; foreach (var (key, value) in bindParams) diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index b0e3e9b37..30d276b61 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -5,7 +5,6 @@ using GitHub.Copilot.SDK.Test.Harness; using Microsoft.Extensions.AI; using System.ComponentModel; -using System.Text.Json; using Xunit; using Xunit.Abstractions; using RpcPermissionDecisionApproveOnce = GitHub.Copilot.SDK.Rpc.PermissionDecisionApproveOnce; @@ -142,7 +141,7 @@ await session1.SendAsync(new MessageOptions var toolResult = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolEvent.Data.RequestId, - result: JsonDocument.Parse("\"EXTERNAL_RESUMED_BETA\"").RootElement.Clone()); + result: "EXTERNAL_RESUMED_BETA"); Assert.True(toolResult.Success); var answer = await TestHelper.GetFinalAssistantMessageAsync(session2, PendingWorkTimeout); @@ -211,7 +210,7 @@ await session1.SendAsync(new MessageOptions var resumedResult = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolEvent.Data.RequestId, - result: JsonDocument.Parse("\"EXTERNAL_RESUMED_BETA\"").RootElement.Clone()); + result: "EXTERNAL_RESUMED_BETA"); Assert.True(resumedResult.Success); // continuePendingWork=false may interrupt agent continuation before this response, @@ -288,11 +287,11 @@ await Task.WhenAll( var toolB = toolEvents["pending_lookup_b"]; var resultB = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolB.Data.RequestId, - result: JsonDocument.Parse("\"PARALLEL_B_BETA\"").RootElement.Clone()); + result: "PARALLEL_B_BETA"); Assert.True(resultB.Success); var resultA = await session2.Rpc.Tools.HandlePendingToolCallAsync( toolA.Data.RequestId, - result: JsonDocument.Parse("\"PARALLEL_A_ALPHA\"").RootElement.Clone()); + result: "PARALLEL_A_ALPHA"); Assert.True(resultA.Success); await session2.DisposeAsync(); diff --git a/dotnet/test/E2E/RpcMcpConfigE2ETests.cs b/dotnet/test/E2E/RpcMcpConfigE2ETests.cs index 87ccc5335..179fc4828 100644 --- a/dotnet/test/E2E/RpcMcpConfigE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpConfigE2ETests.cs @@ -34,11 +34,11 @@ public async Task Should_Call_Server_Mcp_Config_Rpcs() try { - await Client.Rpc.Mcp.Config.AddAsync(serverName, JsonSerializer.SerializeToElement(config, TestSharedJsonContext.Default.DictionaryStringObject)); + await Client.Rpc.Mcp.Config.AddAsync(serverName, config); var afterAdd = await Client.Rpc.Mcp.Config.ListAsync(); Assert.Contains(serverName, afterAdd.Servers.Keys); - await Client.Rpc.Mcp.Config.UpdateAsync(serverName, JsonSerializer.SerializeToElement(updatedConfig, TestSharedJsonContext.Default.DictionaryStringObject)); + await Client.Rpc.Mcp.Config.UpdateAsync(serverName, updatedConfig); var afterUpdate = await Client.Rpc.Mcp.Config.ListAsync(); var updated = GetServerConfig(afterUpdate, serverName); Assert.Equal("node", updated.GetProperty("command").GetString()); @@ -84,7 +84,7 @@ public async Task Should_RoundTrip_Http_Mcp_Oauth_Config_Rpc() try { - await Client.Rpc.Mcp.Config.AddAsync(serverName, JsonSerializer.SerializeToElement(config, TestSharedJsonContext.Default.McpServerConfig)); + await Client.Rpc.Mcp.Config.AddAsync(serverName, config); var afterAdd = await Client.Rpc.Mcp.Config.ListAsync(); var added = GetServerConfig(afterAdd, serverName); Assert.Equal("http", added.GetProperty("type").GetString()); @@ -94,7 +94,7 @@ public async Task Should_RoundTrip_Http_Mcp_Oauth_Config_Rpc() Assert.False(added.GetProperty("oauthPublicClient").GetBoolean()); Assert.Equal("client_credentials", added.GetProperty("oauthGrantType").GetString()); - await Client.Rpc.Mcp.Config.UpdateAsync(serverName, JsonSerializer.SerializeToElement(updatedConfig, TestSharedJsonContext.Default.McpServerConfig)); + await Client.Rpc.Mcp.Config.UpdateAsync(serverName, updatedConfig); var afterUpdate = await Client.Rpc.Mcp.Config.ListAsync(); var updated = GetServerConfig(afterUpdate, serverName); Assert.Equal("https://example.com/updated-mcp", updated.GetProperty("url").GetString()); diff --git a/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs b/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs index 0813ac981..6e8860964 100644 --- a/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs +++ b/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs @@ -4,7 +4,6 @@ using GitHub.Copilot.SDK.Rpc; using GitHub.Copilot.SDK.Test.Harness; -using System.Text.Json; using Xunit; using Xunit.Abstractions; @@ -144,7 +143,7 @@ public async Task Should_Return_Expected_Results_For_Missing_Pending_Handler_Req var tool = await session.Rpc.Tools.HandlePendingToolCallAsync( requestId: "missing-tool-request", - result: JsonDocument.Parse("\"tool result\"").RootElement.Clone()); + result: "tool result"); Assert.False(tool.Success); var command = await session.Rpc.Commands.HandlePendingCommandAsync( diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index 70373b925..fb1e57fc9 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -607,7 +607,7 @@ protected override Task RemoveAsync(string path, bool recursive, bool force, Can protected override Task RenameAsync(string src, string dest, CancellationToken cancellationToken) => Task.FromException(exception); - Task ISessionFsSqliteProvider.QueryAsync(SessionFsSqliteQueryType queryType, string query, IDictionary? bindParams, CancellationToken cancellationToken) => + Task ISessionFsSqliteProvider.QueryAsync(SessionFsSqliteQueryType queryType, string query, IDictionary? bindParams, CancellationToken cancellationToken) => Task.FromException(exception); Task ISessionFsSqliteProvider.ExistsAsync(CancellationToken cancellationToken) => diff --git a/dotnet/test/E2E/ToolResultsE2ETests.cs b/dotnet/test/E2E/ToolResultsE2ETests.cs index 8762b4d2a..fdc2654c6 100644 --- a/dotnet/test/E2E/ToolResultsE2ETests.cs +++ b/dotnet/test/E2E/ToolResultsE2ETests.cs @@ -111,10 +111,10 @@ static ToolResultAIContent AnalyzeCode([Description("File to analyze")] string f { TextResultForLlm = $"Analysis of {file}: no issues found", ResultType = "success", - ToolTelemetry = new Dictionary + ToolTelemetry = new Dictionary { - ["metrics"] = JsonDocument.Parse("""{"analysisTimeMs":150}""").RootElement.Clone(), - ["properties"] = JsonDocument.Parse("""{"analyzer":"eslint"}""").RootElement.Clone(), + ["metrics"] = new Dictionary { ["analysisTimeMs"] = 150 }, + ["properties"] = new Dictionary { ["analyzer"] = "eslint" }, }, }); } diff --git a/dotnet/test/TestJsonContext.cs b/dotnet/test/TestJsonContext.cs deleted file mode 100644 index cb41df2a1..000000000 --- a/dotnet/test/TestJsonContext.cs +++ /dev/null @@ -1,16 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------------------------------------------*/ - -using System.Text.Json.Serialization; - -namespace GitHub.Copilot.SDK.Test; - -[JsonSourceGenerationOptions(System.Text.Json.JsonSerializerDefaults.Web)] -[JsonSerializable(typeof(string[]))] -[JsonSerializable(typeof(Dictionary))] -[JsonSerializable(typeof(Dictionary))] -[JsonSerializable(typeof(McpServerConfig))] -[JsonSerializable(typeof(McpHttpServerConfig))] -[JsonSerializable(typeof(McpStdioServerConfig))] -internal partial class TestSharedJsonContext : JsonSerializerContext; diff --git a/dotnet/test/Unit/SessionEventSerializationTests.cs b/dotnet/test/Unit/SessionEventSerializationTests.cs index 6f009fcdf..3622821dc 100644 --- a/dotnet/test/Unit/SessionEventSerializationTests.cs +++ b/dotnet/test/Unit/SessionEventSerializationTests.cs @@ -66,7 +66,7 @@ public class SessionEventSerializationTests Content = "ok", DetailedContent = "ok", }, - ToolTelemetry = new Dictionary + ToolTelemetry = new Dictionary { ["properties"] = ParseJsonElement("""{"command":"view"}"""), ["metrics"] = ParseJsonElement("""{"resultLength":2}"""), diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 9ea3c07d8..8fd6b6f58 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -275,7 +275,6 @@ function isNonNullableCSharpValueType(typeName: string): boolean { "long", "DateTimeOffset", "TimeSpan", - "JsonElement", ].includes(typeName) || generatedEnums.has(typeName) || emittedRpcEnumResultTypes.has(typeName) || externalRpcValueTypes.has(typeName); } @@ -362,7 +361,7 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: if (type === "boolean") return required ? "bool" : "bool?"; if (type === "array") { const items = schema.items as JSONSchema7 | undefined; - const itemType = items ? schemaTypeToCSharp(items, true, knownTypes) : "JsonElement"; + const itemType = items ? schemaTypeToCSharp(items, true, knownTypes) : "object"; return required ? `${itemType}[]` : `${itemType}[]?`; } if (type === "object") { @@ -370,9 +369,9 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: const valueType = schemaTypeToCSharp(schema.additionalProperties as JSONSchema7, true, knownTypes); return required ? `IDictionary` : `IDictionary?`; } - return required ? "JsonElement" : "JsonElement?"; + return required ? "object" : "object?"; } - return required ? "JsonElement" : "JsonElement?"; + return required ? "object" : "object?"; } /** Tracks whether any TimeSpan property was emitted so the converter can be generated. */ @@ -1146,12 +1145,12 @@ function resolveSessionPropertyType( } const unionType = tryGenerateSessionJsonUnionType(propSchema, parentClassName, propName, knownTypes, nestedClasses, enumOutput); if (unionType) return isRequired ? unionType : `${unionType}?`; - return !isRequired ? "JsonElement?" : "JsonElement"; + return !isRequired ? "object?" : "object"; } if (propSchema.oneOf) { const unionType = tryGenerateSessionJsonUnionType(propSchema, parentClassName, propName, knownTypes, nestedClasses, enumOutput); if (unionType) return isRequired ? unionType : `${unionType}?`; - return !isRequired ? "JsonElement?" : "JsonElement"; + return !isRequired ? "object?" : "object"; } if (propSchema.enum && Array.isArray(propSchema.enum)) { const enumName = getOrCreateEnum(parentClassName, propName, propSchema.enum as string[], enumOutput, propSchema.description, getEnumValueDescriptions(propSchema), propSchema.title as string | undefined, isSchemaDeprecated(propSchema), isSchemaExperimental(propSchema)); @@ -1611,6 +1610,7 @@ function emitRpcClass( let propAccessors = "{ get; set; }"; if (isReq && !csharpType.endsWith("?")) { if (csharpType === "string") defaultVal = " = string.Empty;"; + else if (csharpType === "object") defaultVal = " = null!;"; else if (csharpType.startsWith("IList<")) { propAccessors = "{ get => field ??= []; set; }"; } else if (csharpType.startsWith("IDictionary<")) { From 2c64f30ef81773eef5b8e303e5214815341c4957 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 17:47:49 +0100 Subject: [PATCH 20/40] Post-revert cleanup for Phase 1 revert - Re-ran C# codegen so Generated/Rpc.cs reflects the reverted csharp.ts (a handful of opaque-shape properties go back to object/dict). - Fixed one test that had been adapted to the JsonElement variant of ToolResultObject.ToolTelemetry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 1281 ++++------------- .../E2E/HookLifecycleAndOutputE2ETests.cs | 2 +- 2 files changed, 242 insertions(+), 1041 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 2bd4910a2..54ec6d48f 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -708,8 +708,7 @@ public sealed class SessionList } /// Optional filter applied to the returned sessions. -[Experimental(Diagnostics.Experimental)] -public sealed class SessionListFilter +public sealed class SessionsListRequestFilter { /// Match sessions whose context.branch equals this value. [JsonPropertyName("branch")] @@ -734,7 +733,7 @@ internal sealed class SessionsListRequest { /// Optional filter applied to the returned sessions. [JsonPropertyName("filter")] - public SessionListFilter? Filter { get; set; } + public SessionsListRequestFilter? Filter { get; set; } /// When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. [JsonPropertyName("metadataLimit")] @@ -1075,7 +1074,6 @@ internal sealed class SessionsSetAdditionalPluginsRequest } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionSuspendRequest { /// Target session identifier. @@ -1084,7 +1082,6 @@ internal sealed class SessionSuspendRequest } /// Result of sending a user message. -[Experimental(Diagnostics.Experimental)] public sealed class SendResult { /// Unique identifier assigned to the message. @@ -1094,7 +1091,6 @@ public sealed class SendResult /// A user message attachment — a file, directory, code selection, blob, or GitHub reference. /// Polymorphic base type discriminated by type. -[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -1112,7 +1108,6 @@ public partial class SendAttachment /// Optional line range to scope the attachment to a specific section of the file. -[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentFileLineRange { /// End line number (1-based, inclusive). @@ -1126,7 +1121,6 @@ public sealed class SendAttachmentFileLineRange /// File attachment. /// The file variant of . -[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentFile : SendAttachment { /// @@ -1149,7 +1143,6 @@ public partial class SendAttachmentFile : SendAttachment /// Directory attachment. /// The directory variant of . -[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentDirectory : SendAttachment { /// @@ -1166,7 +1159,6 @@ public partial class SendAttachmentDirectory : SendAttachment } /// End position of the selection. -[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentSelectionDetailsEnd { /// End character offset within the line (0-based). @@ -1179,7 +1171,6 @@ public sealed class SendAttachmentSelectionDetailsEnd } /// Start position of the selection. -[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentSelectionDetailsStart { /// Start character offset within the line (0-based). @@ -1192,7 +1183,6 @@ public sealed class SendAttachmentSelectionDetailsStart } /// Position range of the selection within the file. -[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentSelectionDetails { /// End position of the selection. @@ -1206,7 +1196,6 @@ public sealed class SendAttachmentSelectionDetails /// Code selection attachment from an editor. /// The selection variant of . -[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentSelection : SendAttachment { /// @@ -1232,7 +1221,6 @@ public partial class SendAttachmentSelection : SendAttachment /// GitHub issue, pull request, or discussion reference. /// The github_reference variant of . -[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentGithubReference : SendAttachment { /// @@ -1264,7 +1252,6 @@ public partial class SendAttachmentGithubReference : SendAttachment /// Blob attachment with inline base64-encoded data. /// The blob variant of . -[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentBlob : SendAttachment { /// @@ -1287,7 +1274,6 @@ public partial class SendAttachmentBlob : SendAttachment } /// Parameters for sending a user message to the session. -[Experimental(Diagnostics.Experimental)] internal sealed class SendRequest { /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. @@ -1348,7 +1334,6 @@ internal sealed class SendRequest } /// Result of aborting the current turn. -[Experimental(Diagnostics.Experimental)] public sealed class AbortResult { /// Error message if the abort failed. @@ -1361,7 +1346,6 @@ public sealed class AbortResult } /// Parameters for aborting the current turn. -[Experimental(Diagnostics.Experimental)] internal sealed class AbortRequest { /// Finite reason code describing why the current turn was aborted. @@ -1374,7 +1358,6 @@ internal sealed class AbortRequest } /// Parameters for shutting down the session. -[Experimental(Diagnostics.Experimental)] internal sealed class ShutdownRequest { /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. @@ -1391,7 +1374,6 @@ internal sealed class ShutdownRequest } /// Identifier of the session event that was emitted for the log message. -[Experimental(Diagnostics.Experimental)] public sealed class LogResult { /// The unique identifier of the emitted session event. @@ -1400,7 +1382,6 @@ public sealed class LogResult } /// Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. -[Experimental(Diagnostics.Experimental)] internal sealed class LogRequest { /// When true, the message is transient and not persisted to the session event log on disk. @@ -1435,7 +1416,6 @@ internal sealed class LogRequest } /// Authentication status and account metadata for the session. -[Experimental(Diagnostics.Experimental)] public sealed class SessionAuthStatus { /// Authentication type. @@ -1466,7 +1446,6 @@ public sealed class SessionAuthStatus } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionAuthGetStatusRequest { /// Target session identifier. @@ -1475,7 +1454,6 @@ internal sealed class SessionAuthGetStatusRequest } /// Indicates whether the credential update succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class SessionSetCredentialsResult { /// Whether the operation succeeded. @@ -1485,7 +1463,6 @@ public sealed class SessionSetCredentialsResult /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. /// Polymorphic base type discriminated by type. -[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -1505,7 +1482,6 @@ public partial class AuthInfo /// Schema for the `CopilotUserResponseEndpoints` type. -[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseEndpoints { /// Gets or sets the api value. @@ -1538,7 +1514,6 @@ public sealed class CopilotUserResponseOrganizationListItem } /// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. -[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshotsChat { /// Gets or sets the entitlement value. @@ -1591,7 +1566,6 @@ public sealed class CopilotUserResponseQuotaSnapshotsChat } /// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. -[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshotsCompletions { /// Gets or sets the entitlement value. @@ -1644,7 +1618,6 @@ public sealed class CopilotUserResponseQuotaSnapshotsCompletions } /// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. -[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshotsPremiumInteractions { /// Gets or sets the entitlement value. @@ -1697,7 +1670,6 @@ public sealed class CopilotUserResponseQuotaSnapshotsPremiumInteractions } /// Schema for the `CopilotUserResponseQuotaSnapshots` type. -[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshots { /// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. @@ -1714,7 +1686,6 @@ public sealed class CopilotUserResponseQuotaSnapshots } /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. -[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponse { /// Gets or sets the access_type_sku value. @@ -1812,7 +1783,6 @@ public sealed class CopilotUserResponse /// Schema for the `HMACAuthInfo` type. /// The hmac variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoHmac : AuthInfo { /// @@ -1835,7 +1805,6 @@ public partial class AuthInfoHmac : AuthInfo /// Schema for the `EnvAuthInfo` type. /// The env variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoEnv : AuthInfo { /// @@ -1867,7 +1836,6 @@ public partial class AuthInfoEnv : AuthInfo /// Schema for the `TokenAuthInfo` type. /// The token variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoToken : AuthInfo { /// @@ -1890,7 +1858,6 @@ public partial class AuthInfoToken : AuthInfo /// Schema for the `CopilotApiTokenAuthInfo` type. /// The copilot-api-token variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoCopilotApiToken : AuthInfo { /// @@ -1909,7 +1876,6 @@ public partial class AuthInfoCopilotApiToken : AuthInfo /// Schema for the `UserAuthInfo` type. /// The user variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoUser : AuthInfo { /// @@ -1932,7 +1898,6 @@ public partial class AuthInfoUser : AuthInfo /// Schema for the `GhCliAuthInfo` type. /// The gh-cli variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoGhCli : AuthInfo { /// @@ -1959,7 +1924,6 @@ public partial class AuthInfoGhCli : AuthInfo /// Schema for the `ApiKeyAuthInfo` type. /// The api-key variant of . -[Experimental(Diagnostics.Experimental)] public partial class AuthInfoApiKey : AuthInfo { /// @@ -1981,7 +1945,6 @@ public partial class AuthInfoApiKey : AuthInfo } /// New auth credentials to install on the session. Omit to leave credentials unchanged. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionSetCredentialsParams { /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. @@ -1994,7 +1957,6 @@ internal sealed class SessionSetCredentialsParams } /// The currently selected model and reasoning effort for the session. -[Experimental(Diagnostics.Experimental)] public sealed class CurrentModel { /// Currently active model identifier. @@ -2007,7 +1969,6 @@ public sealed class CurrentModel } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionModelGetCurrentRequest { /// Target session identifier. @@ -2016,7 +1977,6 @@ internal sealed class SessionModelGetCurrentRequest } /// The model identifier active on the session after the switch. -[Experimental(Diagnostics.Experimental)] public sealed class ModelSwitchToResult { /// Currently active model identifier after the switch. @@ -2025,7 +1985,6 @@ public sealed class ModelSwitchToResult } /// Vision-specific limits. -[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverrideLimitsVision { /// Maximum image size in bytes. @@ -2042,7 +2001,6 @@ public sealed class ModelCapabilitiesOverrideLimitsVision } /// Token limits for prompts, outputs, and context window. -[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverrideLimits { /// Maximum total context window size in tokens. @@ -2063,7 +2021,6 @@ public sealed class ModelCapabilitiesOverrideLimits } /// Feature flags indicating what the model supports. -[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverrideSupports { /// Whether this model supports reasoning effort configuration. @@ -2076,7 +2033,6 @@ public sealed class ModelCapabilitiesOverrideSupports } /// Override individual model capabilities resolved by the runtime. -[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverride { /// Token limits for prompts, outputs, and context window. @@ -2089,7 +2045,6 @@ public sealed class ModelCapabilitiesOverride } /// Target model identifier and optional reasoning effort, summary, and capability overrides. -[Experimental(Diagnostics.Experimental)] internal sealed class ModelSwitchToRequest { /// Override individual model capabilities resolved by the runtime. @@ -2114,7 +2069,6 @@ internal sealed class ModelSwitchToRequest } /// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. -[Experimental(Diagnostics.Experimental)] public sealed class ModelSetReasoningEffortResult { /// Reasoning effort level recorded on the session after the update. @@ -2123,7 +2077,6 @@ public sealed class ModelSetReasoningEffortResult } /// Reasoning effort level to apply to the currently selected model. -[Experimental(Diagnostics.Experimental)] internal sealed class ModelSetReasoningEffortRequest { /// Reasoning effort level to apply to the currently selected model. The host is responsible for validating the value against the model's supported levels before calling. @@ -2136,7 +2089,6 @@ internal sealed class ModelSetReasoningEffortRequest } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionModeGetRequest { /// Target session identifier. @@ -2145,7 +2097,6 @@ internal sealed class SessionModeGetRequest } /// Agent interaction mode to apply to the session. -[Experimental(Diagnostics.Experimental)] internal sealed class ModeSetRequest { /// The session mode the agent is operating in. @@ -2158,7 +2109,6 @@ internal sealed class ModeSetRequest } /// The session's friendly name, or null when not yet set. -[Experimental(Diagnostics.Experimental)] public sealed class NameGetResult { /// The session name (user-set or auto-generated), or null if not yet set. @@ -2167,7 +2117,6 @@ public sealed class NameGetResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionNameGetRequest { /// Target session identifier. @@ -2176,7 +2125,6 @@ internal sealed class SessionNameGetRequest } /// New friendly name to apply to the session. -[Experimental(Diagnostics.Experimental)] internal sealed class NameSetRequest { /// New session name (1–100 characters, trimmed of leading/trailing whitespace). @@ -2192,7 +2140,6 @@ internal sealed class NameSetRequest } /// Indicates whether the auto-generated summary was applied as the session's name. -[Experimental(Diagnostics.Experimental)] public sealed class NameSetAutoResult { /// Whether the auto-generated summary was persisted. False if the session already has a user-set name, the summary normalized to empty, or the session does not have a workspace. @@ -2201,7 +2148,6 @@ public sealed class NameSetAutoResult } /// Auto-generated session summary to apply as the session's name when no user-set name exists. -[Experimental(Diagnostics.Experimental)] internal sealed class NameSetAutoRequest { /// Target session identifier. @@ -2214,7 +2160,6 @@ internal sealed class NameSetAutoRequest } /// Existence, contents, and resolved path of the session plan file. -[Experimental(Diagnostics.Experimental)] public sealed class PlanReadResult { /// The content of the plan file, or null if it does not exist. @@ -2231,7 +2176,6 @@ public sealed class PlanReadResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionPlanReadRequest { /// Target session identifier. @@ -2240,7 +2184,6 @@ internal sealed class SessionPlanReadRequest } /// Replacement contents to write to the session plan file. -[Experimental(Diagnostics.Experimental)] internal sealed class PlanUpdateRequest { /// The new content for the plan file. @@ -2253,7 +2196,6 @@ internal sealed class PlanUpdateRequest } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionPlanDeleteRequest { /// Target session identifier. @@ -2284,15 +2226,13 @@ public sealed class WorkspacesGetWorkspaceResultWorkspace [JsonPropertyName("git_root")] public string? GitRoot { get; set; } - /// Allowed values for the `WorkspacesWorkspaceDetailsHostType` enumeration. + /// Gets or sets the host_type value. [JsonPropertyName("host_type")] - public WorkspacesWorkspaceDetailsHostType? HostType { get; set; } + public WorkspacesGetWorkspaceResultWorkspaceHostType? HostType { get; set; } /// Gets or sets the id value. - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] - [MinLength(1)] [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + public Guid Id { get; set; } /// Gets or sets the mc_last_event_id value. [JsonPropertyName("mc_last_event_id")] @@ -2332,7 +2272,6 @@ public sealed class WorkspacesGetWorkspaceResultWorkspace } /// Current workspace metadata for the session, including its absolute filesystem path when available. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesGetWorkspaceResult { /// Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). @@ -2345,7 +2284,6 @@ public sealed class WorkspacesGetWorkspaceResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionWorkspacesGetWorkspaceRequest { /// Target session identifier. @@ -2354,7 +2292,6 @@ internal sealed class SessionWorkspacesGetWorkspaceRequest } /// Relative paths of files stored in the session workspace files directory. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesListFilesResult { /// Relative file paths in the workspace files directory. @@ -2363,7 +2300,6 @@ public sealed class WorkspacesListFilesResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionWorkspacesListFilesRequest { /// Target session identifier. @@ -2372,7 +2308,6 @@ internal sealed class SessionWorkspacesListFilesRequest } /// Contents of the requested workspace file as a UTF-8 string. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesReadFileResult { /// File content as a UTF-8 string. @@ -2381,7 +2316,6 @@ public sealed class WorkspacesReadFileResult } /// Relative path of the workspace file to read. -[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesReadFileRequest { /// Relative path within the workspace files directory. @@ -2394,7 +2328,6 @@ internal sealed class WorkspacesReadFileRequest } /// Relative path and UTF-8 content for the workspace file to create or overwrite. -[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesCreateFileRequest { /// File content to write as a UTF-8 string. @@ -2411,7 +2344,6 @@ internal sealed class WorkspacesCreateFileRequest } /// Schema for the `WorkspacesCheckpoints` type. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesCheckpoints { /// Filename of the checkpoint within the workspace checkpoints directory. @@ -2428,7 +2360,6 @@ public sealed class WorkspacesCheckpoints } /// Workspace checkpoints in chronological order; empty when the workspace is not enabled. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesListCheckpointsResult { /// Workspace checkpoints in chronological order. Empty when workspace is not enabled. @@ -2437,7 +2368,6 @@ public sealed class WorkspacesListCheckpointsResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionWorkspacesListCheckpointsRequest { /// Target session identifier. @@ -2446,7 +2376,6 @@ internal sealed class SessionWorkspacesListCheckpointsRequest } /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesReadCheckpointResult { /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. @@ -2455,7 +2384,6 @@ public sealed class WorkspacesReadCheckpointResult } /// Checkpoint number to read. -[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesReadCheckpointRequest { /// Checkpoint number to read. @@ -2484,7 +2412,6 @@ public sealed class WorkspacesSaveLargePasteResultSaved } /// Descriptor for the saved paste file, or null when the workspace is unavailable. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesSaveLargePasteResult { /// Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions). @@ -2493,7 +2420,6 @@ public sealed class WorkspacesSaveLargePasteResult } /// Pasted content to save as a UTF-8 file in the session workspace. -[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesSaveLargePasteRequest { /// Pasted content to save as a UTF-8 file. @@ -2506,7 +2432,6 @@ internal sealed class WorkspacesSaveLargePasteRequest } /// Schema for the `InstructionsSources` type. -[Experimental(Diagnostics.Experimental)] public sealed class InstructionsSources { /// Glob pattern(s) from frontmatter — when set, this instruction applies only to matching files. @@ -2547,7 +2472,6 @@ public sealed class InstructionsSources } /// Instruction sources loaded for the session, in merge order. -[Experimental(Diagnostics.Experimental)] public sealed class InstructionsGetSourcesResult { /// Instruction sources for the session. @@ -2556,7 +2480,6 @@ public sealed class InstructionsGetSourcesResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionInstructionsGetSourcesRequest { /// Target session identifier. @@ -2970,76 +2893,13 @@ internal sealed class SessionTasksWaitForPendingRequest public string SessionId { get; set; } = string.Empty; } -/// Polymorphic base type discriminated by type. -[JsonPolymorphic( - TypeDiscriminatorPropertyName = "type", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(TasksGetProgressResultProgressAgent), "agent")] -[JsonDerivedType(typeof(TasksGetProgressResultProgressShell), "shell")] -public partial class TasksGetProgressResultProgress -{ - /// The type discriminator. - [JsonPropertyName("type")] - public virtual string Type { get; set; } = string.Empty; -} - - -/// Schema for the `TaskProgressLine` type. -[Experimental(Diagnostics.Experimental)] -public sealed class TaskProgressLine -{ - /// Display message, e.g., "▸ bash", "✓ edit src/foo.ts". - [JsonPropertyName("message")] - public string Message { get; set; } = string.Empty; - - /// ISO 8601 timestamp when this event occurred. - [JsonPropertyName("timestamp")] - public DateTimeOffset Timestamp { get; set; } -} - -/// Schema for the `TaskAgentProgress` type. -/// The agent variant of . -public partial class TasksGetProgressResultProgressAgent : TasksGetProgressResultProgress -{ - /// - [JsonIgnore] - public override string Type => "agent"; - - /// The most recent intent reported by the agent. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("latestIntent")] - public string? LatestIntent { get; set; } - - /// Recent tool execution events converted to display lines. - [JsonPropertyName("recentActivity")] - public required IList RecentActivity { get; set; } -} - -/// Schema for the `TaskShellProgress` type. -/// The shell variant of . -public partial class TasksGetProgressResultProgressShell : TasksGetProgressResultProgress -{ - /// - [JsonIgnore] - public override string Type => "shell"; - - /// Process ID when available. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("pid")] - public long? Pid { get; set; } - - /// Recent stdout/stderr lines from the running shell command. - [JsonPropertyName("recentOutput")] - public required string RecentOutput { get; set; } -} - /// Progress information for the task, or null when no task with that ID is tracked. [Experimental(Diagnostics.Experimental)] public sealed class TasksGetProgressResult { /// Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. [JsonPropertyName("progress")] - public TasksGetProgressResultProgress? Progress { get; set; } + public object? Progress { get; set; } } /// Identifier of the background task to fetch progress for. @@ -3914,7 +3774,6 @@ internal sealed class SessionExtensionsReloadRequest } /// Indicates whether the external tool call result was handled successfully. -[Experimental(Diagnostics.Experimental)] public sealed class HandlePendingToolCallResult { /// Whether the tool call result was handled successfully. @@ -3923,7 +3782,6 @@ public sealed class HandlePendingToolCallResult } /// Pending external tool call request ID, with the tool result or an error describing why it failed. -[Experimental(Diagnostics.Experimental)] internal sealed class HandlePendingToolCallRequest { /// Error message if the tool call failed. @@ -3944,13 +3802,11 @@ internal sealed class HandlePendingToolCallRequest } /// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. -[Experimental(Diagnostics.Experimental)] public sealed class ToolsInitializeAndValidateResult { } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionToolsInitializeAndValidateRequest { /// Target session identifier. @@ -3959,7 +3815,6 @@ internal sealed class SessionToolsInitializeAndValidateRequest } /// Optional unstructured input hint. -[Experimental(Diagnostics.Experimental)] public sealed class SlashCommandInput { /// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). @@ -3980,7 +3835,6 @@ public sealed class SlashCommandInput } /// Schema for the `SlashCommandInfo` type. -[Experimental(Diagnostics.Experimental)] public sealed class SlashCommandInfo { /// Canonical aliases without leading slashes. @@ -4013,7 +3867,6 @@ public sealed class SlashCommandInfo } /// Slash commands available in the session, after applying any include/exclude filters. -[Experimental(Diagnostics.Experimental)] public sealed class CommandList { /// Commands available in this session. @@ -4022,7 +3875,6 @@ public sealed class CommandList } /// Optional filters controlling which command sources to include in the listing. -[Experimental(Diagnostics.Experimental)] public sealed class CommandsListRequest { /// Include runtime built-in commands. @@ -4039,7 +3891,6 @@ public sealed class CommandsListRequest } /// Optional filters controlling which command sources to include in the listing. -[Experimental(Diagnostics.Experimental)] internal sealed class CommandsListRequestWithSession { /// Include runtime built-in commands. @@ -4061,14 +3912,12 @@ internal sealed class CommandsListRequestWithSession /// Result of invoking the slash command (text output, prompt to send to the agent, or completion). /// Polymorphic base type discriminated by kind. -[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] [JsonDerivedType(typeof(SlashCommandInvocationResultText), "text")] [JsonDerivedType(typeof(SlashCommandInvocationResultAgentPrompt), "agent-prompt")] [JsonDerivedType(typeof(SlashCommandInvocationResultCompleted), "completed")] -[JsonDerivedType(typeof(SlashCommandInvocationResultSelectSubcommand), "select-subcommand")] public partial class SlashCommandInvocationResult { /// The type discriminator. @@ -4079,7 +3928,6 @@ public partial class SlashCommandInvocationResult /// Schema for the `SlashCommandTextResult` type. /// The text variant of . -[Experimental(Diagnostics.Experimental)] public partial class SlashCommandInvocationResultText : SlashCommandInvocationResult { /// @@ -4108,7 +3956,6 @@ public partial class SlashCommandInvocationResultText : SlashCommandInvocationRe /// Schema for the `SlashCommandAgentPromptResult` type. /// The agent-prompt variant of . -[Experimental(Diagnostics.Experimental)] public partial class SlashCommandInvocationResultAgentPrompt : SlashCommandInvocationResult { /// @@ -4136,7 +3983,6 @@ public partial class SlashCommandInvocationResultAgentPrompt : SlashCommandInvoc /// Schema for the `SlashCommandCompletedResult` type. /// The completed variant of . -[Experimental(Diagnostics.Experimental)] public partial class SlashCommandInvocationResultCompleted : SlashCommandInvocationResult { /// @@ -4154,52 +4000,7 @@ public partial class SlashCommandInvocationResultCompleted : SlashCommandInvocat public bool? RuntimeSettingsChanged { get; set; } } -/// Schema for the `SlashCommandSelectSubcommandOption` type. -[Experimental(Diagnostics.Experimental)] -public sealed class SlashCommandSelectSubcommandOption -{ - /// Human-readable description of the subcommand. - [JsonPropertyName("description")] - public string Description { get; set; } = string.Empty; - - /// Optional group label for organizing options. - [JsonPropertyName("group")] - public string? Group { get; set; } - - /// Subcommand name to invoke. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; -} - -/// Schema for the `SlashCommandSelectSubcommandResult` type. -/// The select-subcommand variant of . -[Experimental(Diagnostics.Experimental)] -public partial class SlashCommandInvocationResultSelectSubcommand : SlashCommandInvocationResult -{ - /// - [JsonIgnore] - public override string Kind => "select-subcommand"; - - /// Parent command name that requires subcommand selection. - [JsonPropertyName("command")] - public required string Command { get; set; } - - /// Available subcommand options for the client to present. - [JsonPropertyName("options")] - public required IList Options { get; set; } - - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("runtimeSettingsChanged")] - public bool? RuntimeSettingsChanged { get; set; } - - /// Human-readable title for the selection UI. - [JsonPropertyName("title")] - public required string Title { get; set; } -} - /// Slash command name and optional raw input string to invoke. -[Experimental(Diagnostics.Experimental)] internal sealed class CommandsInvokeRequest { /// Raw input after the command name. @@ -4216,7 +4017,6 @@ internal sealed class CommandsInvokeRequest } /// Indicates whether the pending client-handled command was completed successfully. -[Experimental(Diagnostics.Experimental)] public sealed class CommandsHandlePendingCommandResult { /// Whether the command was handled successfully. @@ -4225,7 +4025,6 @@ public sealed class CommandsHandlePendingCommandResult } /// Pending command request ID and an optional error if the client handler failed. -[Experimental(Diagnostics.Experimental)] internal sealed class CommandsHandlePendingCommandRequest { /// Error message if the command handler failed. @@ -4242,7 +4041,6 @@ internal sealed class CommandsHandlePendingCommandRequest } /// Error message produced while executing the command, if any. -[Experimental(Diagnostics.Experimental)] public sealed class ExecuteCommandResult { /// Error message produced while executing the command, if any. Omitted when the handler succeeded. @@ -4251,7 +4049,6 @@ public sealed class ExecuteCommandResult } /// Slash command name and argument string to execute synchronously. -[Experimental(Diagnostics.Experimental)] internal sealed class ExecuteCommandParams { /// Argument string to pass to the command (empty string if none). @@ -4268,7 +4065,6 @@ internal sealed class ExecuteCommandParams } /// Indicates whether the command was accepted into the local execution queue. -[Experimental(Diagnostics.Experimental)] public sealed class EnqueueCommandResult { /// True when the command was accepted into the local execution queue. False when the call targets a session that does not support local command queueing (e.g. remote sessions). @@ -4277,7 +4073,6 @@ public sealed class EnqueueCommandResult } /// Slash-prefixed command string to enqueue for FIFO processing. -[Experimental(Diagnostics.Experimental)] internal sealed class EnqueueCommandParams { /// Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO with any in-flight items; if the session is idle, processing kicks off immediately. @@ -4290,7 +4085,6 @@ internal sealed class EnqueueCommandParams } /// Indicates whether the queued-command response was matched to a pending request. -[Experimental(Diagnostics.Experimental)] public sealed class CommandsRespondToQueuedCommandResult { /// Whether a pending queued command with the given request ID was found and resolved. False when the request was already resolved, cancelled, or unknown. @@ -4300,7 +4094,6 @@ public sealed class CommandsRespondToQueuedCommandResult /// Result of the queued command execution. /// Data type discriminated by handled. -[Experimental(Diagnostics.Experimental)] public partial class QueuedCommandResult { /// The boolean discriminator. @@ -4314,7 +4107,6 @@ public partial class QueuedCommandResult } /// Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). -[Experimental(Diagnostics.Experimental)] internal sealed class CommandsRespondToQueuedCommandRequest { /// Request ID from the `command.queued` event the host is responding to. @@ -4344,7 +4136,6 @@ internal sealed class TelemetrySetFeatureOverridesRequest } /// The elicitation response (accept with form values, decline, or cancel). -[Experimental(Diagnostics.Experimental)] public sealed class UIElicitationResponse { /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). @@ -4357,7 +4148,6 @@ public sealed class UIElicitationResponse } /// JSON Schema describing the form fields to present to the user. -[Experimental(Diagnostics.Experimental)] public sealed class UIElicitationSchema { /// Form field definitions, keyed by field name. @@ -4374,7 +4164,6 @@ public sealed class UIElicitationSchema } /// Prompt message and JSON schema describing the form fields to elicit from the user. -[Experimental(Diagnostics.Experimental)] internal sealed class UIElicitationRequest { /// Message describing what information is needed from the user. @@ -4391,7 +4180,6 @@ internal sealed class UIElicitationRequest } /// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. -[Experimental(Diagnostics.Experimental)] public sealed class UIElicitationResult { /// Whether the response was accepted. False if the request was already resolved by another client. @@ -4400,7 +4188,6 @@ public sealed class UIElicitationResult } /// Pending elicitation request ID and the user's response (accept/decline/cancel + form values). -[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingElicitationRequest { /// The unique request ID from the elicitation.requested event. @@ -4417,7 +4204,6 @@ internal sealed class UIHandlePendingElicitationRequest } /// Indicates whether the pending UI request was resolved by this call. -[Experimental(Diagnostics.Experimental)] public sealed class UIHandlePendingResult { /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. @@ -4426,7 +4212,6 @@ public sealed class UIHandlePendingResult } /// Schema for the `UIUserInputResponse` type. -[Experimental(Diagnostics.Experimental)] public sealed class UIUserInputResponse { /// The user's answer text. @@ -4439,7 +4224,6 @@ public sealed class UIUserInputResponse } /// Request ID of a pending `user_input.requested` event and the user's response. -[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingUserInputRequest { /// The unique request ID from the user_input.requested event. @@ -4456,13 +4240,11 @@ internal sealed class UIHandlePendingUserInputRequest } /// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. -[Experimental(Diagnostics.Experimental)] public sealed class UIHandlePendingSamplingResponse { } /// Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). -[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingSamplingRequest { /// The unique request ID from the sampling.requested event. @@ -4479,7 +4261,6 @@ internal sealed class UIHandlePendingSamplingRequest } /// Request ID of a pending `auto_mode_switch.requested` event and the user's response. -[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingAutoModeSwitchRequest { /// The unique request ID from the auto_mode_switch.requested event. @@ -4496,7 +4277,6 @@ internal sealed class UIHandlePendingAutoModeSwitchRequest } /// Schema for the `UIExitPlanModeResponse` type. -[Experimental(Diagnostics.Experimental)] public sealed class UIExitPlanModeResponse { /// Whether the plan was approved. @@ -4517,7 +4297,6 @@ public sealed class UIExitPlanModeResponse } /// Request ID of a pending `exit_plan_mode.requested` event and the user's response. -[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingExitPlanModeRequest { /// The unique request ID from the exit_plan_mode.requested event. @@ -4534,7 +4313,6 @@ internal sealed class UIHandlePendingExitPlanModeRequest } /// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). -[Experimental(Diagnostics.Experimental)] public sealed class UIRegisterDirectAutoModeSwitchHandlerResult { /// Opaque handle representing the registration. Pass this same handle to `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. Multiple registrations are reference-counted; the server bridge will only dispatch auto-mode-switch requests when no handles are active. @@ -4543,7 +4321,6 @@ public sealed class UIRegisterDirectAutoModeSwitchHandlerResult } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] internal sealed class SessionUiRegisterDirectAutoModeSwitchHandlerRequest { /// Target session identifier. @@ -4552,7 +4329,6 @@ internal sealed class SessionUiRegisterDirectAutoModeSwitchHandlerRequest } /// Indicates whether the handle was active and the registration count was decremented. -[Experimental(Diagnostics.Experimental)] public sealed class UIUnregisterDirectAutoModeSwitchHandlerResult { /// True if the handle was active and decremented the counter; false if the handle was unknown. @@ -4561,7 +4337,6 @@ public sealed class UIUnregisterDirectAutoModeSwitchHandlerResult } /// Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. -[Experimental(Diagnostics.Experimental)] internal sealed class UIUnregisterDirectAutoModeSwitchHandlerRequest { /// Handle previously returned by `registerDirectAutoModeSwitchHandler`. @@ -4574,7 +4349,6 @@ internal sealed class UIUnregisterDirectAutoModeSwitchHandlerRequest } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureResult { /// Whether the operation succeeded. @@ -4583,7 +4357,6 @@ public sealed class PermissionsConfigureResult } /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRuleSource { /// Gets or sets the name value. @@ -4596,7 +4369,6 @@ public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRuleSour } /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRule { /// Gets or sets the ifAnyMatch value. @@ -4617,7 +4389,6 @@ public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRule } /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureAdditionalContentExclusionPolicy { /// Gets or sets the last_updated_at value. @@ -4634,7 +4405,6 @@ public sealed class PermissionsConfigureAdditionalContentExclusionPolicy } /// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionPathsConfig { /// Additional directories to allow tool access to (in addition to the session's working directory). When `unrestricted` is true, these are still pre-populated on the UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention completion). @@ -4655,7 +4425,6 @@ public sealed class PermissionPathsConfig } /// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionRulesSet { /// Rules that auto-approve matching requests. @@ -4668,7 +4437,6 @@ public sealed class PermissionRulesSet } /// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionUrlsConfig { /// Initial list of allowed URL/domain patterns. Patterns may include path components. Ignored when `unrestricted` is true. @@ -4681,7 +4449,6 @@ public sealed class PermissionUrlsConfig } /// Patch of permission policy fields to apply (omit a field to leave it unchanged). -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsConfigureParams { /// If specified, replaces the host-supplied GitHub Content Exclusion policies on the session (combined with natively-discovered policies when evaluating tool/file access). Omit to leave the current policies unchanged. @@ -4714,7 +4481,6 @@ internal sealed class PermissionsConfigureParams } /// Indicates whether the permission decision was applied; false when the request was already resolved. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionRequestResult { /// Whether the permission request was handled successfully. @@ -4724,7 +4490,6 @@ public sealed class PermissionRequestResult /// The client's response to the pending permission prompt. /// Polymorphic base type discriminated by kind. -[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -4753,7 +4518,6 @@ public partial class PermissionDecision /// Schema for the `PermissionDecisionApproveOnce` type. /// The approve-once variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveOnce : PermissionDecision { /// @@ -4763,7 +4527,6 @@ public partial class PermissionDecisionApproveOnce : PermissionDecision /// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts). /// Polymorphic base type discriminated by kind. -[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -4786,7 +4549,6 @@ public partial class PermissionDecisionApproveForSessionApproval /// Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type. /// The commands variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalCommands : PermissionDecisionApproveForSessionApproval { /// @@ -4800,7 +4562,6 @@ public partial class PermissionDecisionApproveForSessionApprovalCommands : Permi /// Schema for the `PermissionDecisionApproveForSessionApprovalRead` type. /// The read variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalRead : PermissionDecisionApproveForSessionApproval { /// @@ -4810,7 +4571,6 @@ public partial class PermissionDecisionApproveForSessionApprovalRead : Permissio /// Schema for the `PermissionDecisionApproveForSessionApprovalWrite` type. /// The write variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalWrite : PermissionDecisionApproveForSessionApproval { /// @@ -4820,7 +4580,6 @@ public partial class PermissionDecisionApproveForSessionApprovalWrite : Permissi /// Schema for the `PermissionDecisionApproveForSessionApprovalMcp` type. /// The mcp variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalMcp : PermissionDecisionApproveForSessionApproval { /// @@ -4838,7 +4597,6 @@ public partial class PermissionDecisionApproveForSessionApprovalMcp : Permission /// Schema for the `PermissionDecisionApproveForSessionApprovalMcpSampling` type. /// The mcp-sampling variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalMcpSampling : PermissionDecisionApproveForSessionApproval { /// @@ -4852,7 +4610,6 @@ public partial class PermissionDecisionApproveForSessionApprovalMcpSampling : Pe /// Schema for the `PermissionDecisionApproveForSessionApprovalMemory` type. /// The memory variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalMemory : PermissionDecisionApproveForSessionApproval { /// @@ -4862,7 +4619,6 @@ public partial class PermissionDecisionApproveForSessionApprovalMemory : Permiss /// Schema for the `PermissionDecisionApproveForSessionApprovalCustomTool` type. /// The custom-tool variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalCustomTool : PermissionDecisionApproveForSessionApproval { /// @@ -4876,7 +4632,6 @@ public partial class PermissionDecisionApproveForSessionApprovalCustomTool : Per /// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionManagement` type. /// The extension-management variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalExtensionManagement : PermissionDecisionApproveForSessionApproval { /// @@ -4891,7 +4646,6 @@ public partial class PermissionDecisionApproveForSessionApprovalExtensionManagem /// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` type. /// The extension-permission-access variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess : PermissionDecisionApproveForSessionApproval { /// @@ -4905,7 +4659,6 @@ public partial class PermissionDecisionApproveForSessionApprovalExtensionPermiss /// Schema for the `PermissionDecisionApproveForSession` type. /// The approve-for-session variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSession : PermissionDecision { /// @@ -4925,7 +4678,6 @@ public partial class PermissionDecisionApproveForSession : PermissionDecision /// Approval to persist for this location. /// Polymorphic base type discriminated by kind. -[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -4948,7 +4700,6 @@ public partial class PermissionDecisionApproveForLocationApproval /// Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type. /// The commands variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalCommands : PermissionDecisionApproveForLocationApproval { /// @@ -4962,7 +4713,6 @@ public partial class PermissionDecisionApproveForLocationApprovalCommands : Perm /// Schema for the `PermissionDecisionApproveForLocationApprovalRead` type. /// The read variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalRead : PermissionDecisionApproveForLocationApproval { /// @@ -4972,7 +4722,6 @@ public partial class PermissionDecisionApproveForLocationApprovalRead : Permissi /// Schema for the `PermissionDecisionApproveForLocationApprovalWrite` type. /// The write variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalWrite : PermissionDecisionApproveForLocationApproval { /// @@ -4982,7 +4731,6 @@ public partial class PermissionDecisionApproveForLocationApprovalWrite : Permiss /// Schema for the `PermissionDecisionApproveForLocationApprovalMcp` type. /// The mcp variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalMcp : PermissionDecisionApproveForLocationApproval { /// @@ -5000,7 +4748,6 @@ public partial class PermissionDecisionApproveForLocationApprovalMcp : Permissio /// Schema for the `PermissionDecisionApproveForLocationApprovalMcpSampling` type. /// The mcp-sampling variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalMcpSampling : PermissionDecisionApproveForLocationApproval { /// @@ -5014,7 +4761,6 @@ public partial class PermissionDecisionApproveForLocationApprovalMcpSampling : P /// Schema for the `PermissionDecisionApproveForLocationApprovalMemory` type. /// The memory variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalMemory : PermissionDecisionApproveForLocationApproval { /// @@ -5024,7 +4770,6 @@ public partial class PermissionDecisionApproveForLocationApprovalMemory : Permis /// Schema for the `PermissionDecisionApproveForLocationApprovalCustomTool` type. /// The custom-tool variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalCustomTool : PermissionDecisionApproveForLocationApproval { /// @@ -5038,7 +4783,6 @@ public partial class PermissionDecisionApproveForLocationApprovalCustomTool : Pe /// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionManagement` type. /// The extension-management variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalExtensionManagement : PermissionDecisionApproveForLocationApproval { /// @@ -5053,7 +4797,6 @@ public partial class PermissionDecisionApproveForLocationApprovalExtensionManage /// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` type. /// The extension-permission-access variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess : PermissionDecisionApproveForLocationApproval { /// @@ -5067,7 +4810,6 @@ public partial class PermissionDecisionApproveForLocationApprovalExtensionPermis /// Schema for the `PermissionDecisionApproveForLocation` type. /// The approve-for-location variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocation : PermissionDecision { /// @@ -5085,7 +4827,6 @@ public partial class PermissionDecisionApproveForLocation : PermissionDecision /// Schema for the `PermissionDecisionApprovePermanently` type. /// The approve-permanently variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApprovePermanently : PermissionDecision { /// @@ -5099,7 +4840,6 @@ public partial class PermissionDecisionApprovePermanently : PermissionDecision /// Schema for the `PermissionDecisionReject` type. /// The reject variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionReject : PermissionDecision { /// @@ -5114,7 +4854,6 @@ public partial class PermissionDecisionReject : PermissionDecision /// Schema for the `PermissionDecisionUserNotAvailable` type. /// The user-not-available variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionUserNotAvailable : PermissionDecision { /// @@ -5124,7 +4863,6 @@ public partial class PermissionDecisionUserNotAvailable : PermissionDecision /// Schema for the `PermissionDecisionApproved` type. /// The approved variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproved : PermissionDecision { /// @@ -5134,7 +4872,6 @@ public partial class PermissionDecisionApproved : PermissionDecision /// Schema for the `PermissionDecisionApprovedForSession` type. /// The approved-for-session variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApprovedForSession : PermissionDecision { /// @@ -5148,7 +4885,6 @@ public partial class PermissionDecisionApprovedForSession : PermissionDecision /// Schema for the `PermissionDecisionApprovedForLocation` type. /// The approved-for-location variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApprovedForLocation : PermissionDecision { /// @@ -5166,7 +4902,6 @@ public partial class PermissionDecisionApprovedForLocation : PermissionDecision /// Schema for the `PermissionDecisionCancelled` type. /// The cancelled variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionCancelled : PermissionDecision { /// @@ -5181,7 +4916,6 @@ public partial class PermissionDecisionCancelled : PermissionDecision /// Schema for the `PermissionDecisionDeniedByRules` type. /// The denied-by-rules variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedByRules : PermissionDecision { /// @@ -5195,7 +4929,6 @@ public partial class PermissionDecisionDeniedByRules : PermissionDecision /// Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. /// The denied-no-approval-rule-and-could-not-request-from-user variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser : PermissionDecision { /// @@ -5205,7 +4938,6 @@ public partial class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFro /// Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. /// The denied-interactively-by-user variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedInteractivelyByUser : PermissionDecision { /// @@ -5225,7 +4957,6 @@ public partial class PermissionDecisionDeniedInteractivelyByUser : PermissionDec /// Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. /// The denied-by-content-exclusion-policy variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedByContentExclusionPolicy : PermissionDecision { /// @@ -5243,7 +4974,6 @@ public partial class PermissionDecisionDeniedByContentExclusionPolicy : Permissi /// Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. /// The denied-by-permission-request-hook variant of . -[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedByPermissionRequestHook : PermissionDecision { /// @@ -5262,7 +4992,6 @@ public partial class PermissionDecisionDeniedByPermissionRequestHook : Permissio } /// Pending permission request ID and the decision to apply (approve/reject and scope). -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionDecisionRequest { /// Request ID of the pending permission request. @@ -5279,7 +5008,6 @@ internal sealed class PermissionDecisionRequest } /// Schema for the `PendingPermissionRequest` type. -[Experimental(Diagnostics.Experimental)] public sealed class PendingPermissionRequest { /// The user-facing permission prompt details (commands, write, read, mcp, url, memory, custom-tool, path, hook). @@ -5292,7 +5020,6 @@ public sealed class PendingPermissionRequest } /// List of pending permission requests reconstructed from event history. -[Experimental(Diagnostics.Experimental)] public sealed class PendingPermissionRequestList { /// Pending permission prompts reconstructed from the session's event history. Equivalent to the set of `permission.requested` events that have not yet been followed by a matching `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts that were emitted before the client attached to the session. @@ -5301,7 +5028,6 @@ public sealed class PendingPermissionRequestList } /// No parameters; returns currently-pending permission requests for the session. -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsPendingRequestsRequest { /// Target session identifier. @@ -5310,7 +5036,6 @@ internal sealed class PermissionsPendingRequestsRequest } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsSetApproveAllResult { /// Whether the operation succeeded. @@ -5319,7 +5044,6 @@ public sealed class PermissionsSetApproveAllResult } /// Allow-all toggle for tool permission requests, with an optional telemetry source. -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsSetApproveAllRequest { /// Whether to auto-approve all tool permission requests. @@ -5336,7 +5060,6 @@ internal sealed class PermissionsSetApproveAllRequest } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsModifyRulesResult { /// Whether the operation succeeded. @@ -5345,7 +5068,6 @@ public sealed class PermissionsModifyRulesResult } /// Scope and add/remove instructions for modifying session- or location-scoped permission rules. -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsModifyRulesParams { /// Rules to add to the scope. Applied before `remove`/`removeAll`. @@ -5370,7 +5092,6 @@ internal sealed class PermissionsModifyRulesParams } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsSetRequiredResult { /// Whether the operation succeeded. @@ -5379,7 +5100,6 @@ public sealed class PermissionsSetRequiredResult } /// Toggles whether permission prompts should be bridged into session events for this client. -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsSetRequiredRequest { /// Whether the client wants `permission.requested` events bridged from the session-owned permission service. CLI clients that render prompt UI set this to `true` for as long as their listener is mounted; headless callers leave it unset (the default is `false`). @@ -5392,7 +5112,6 @@ internal sealed class PermissionsSetRequiredRequest } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsResetSessionApprovalsResult { /// Whether the operation succeeded. @@ -5401,7 +5120,6 @@ public sealed class PermissionsResetSessionApprovalsResult } /// No parameters; clears all session-scoped tool permission approvals. -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsResetSessionApprovalsRequest { /// Target session identifier. @@ -5410,387 +5128,97 @@ internal sealed class PermissionsResetSessionApprovalsRequest } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsNotifyPromptShownResult { /// Whether the operation succeeded. [JsonPropertyName("success")] - public bool Success { get; set; } -} - -/// Notification payload describing the permission prompt that the client just rendered. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionPromptShownNotification -{ - /// Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). - [JsonPropertyName("message")] - public string Message { get; set; } = string.Empty; - - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} - -/// Snapshot of the session's allow-listed directories and primary working directory. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionPathsList -{ - /// All directories currently allowed for tool access on this session. - [JsonPropertyName("directories")] - public IList Directories { get => field ??= []; set; } - - /// The primary working directory for this session. - [JsonPropertyName("primary")] - public string Primary { get; set; } = string.Empty; -} - -/// No parameters; returns the session's allow-listed directories. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionsPathsListRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} - -/// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionsPathsAddResult -{ - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } -} - -/// Directory path to add to the session's allowed directories. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionPathsAddParams -{ - /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; - - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} - -/// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionsPathsUpdatePrimaryResult -{ - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } -} - -/// Directory path to set as the session's new primary working directory. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionPathsUpdatePrimaryParams -{ - /// Directory to set as the new primary working directory for the session's permission policy. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; - - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} - -/// Indicates whether the supplied path is within the session's allowed directories. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionPathsAllowedCheckResult -{ - /// Whether the path is within the session's allowed directories. - [JsonPropertyName("allowed")] - public bool Allowed { get; set; } -} - -/// Path to evaluate against the session's allowed directories. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionPathsAllowedCheckParams -{ - /// Path to check against the session's allowed directories. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; - - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} - -/// Indicates whether the supplied path is within the session's workspace directory. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionPathsWorkspaceCheckResult -{ - /// Whether the path is within the session workspace directory. - [JsonPropertyName("allowed")] - public bool Allowed { get; set; } -} - -/// Path to evaluate against the session's workspace (primary) directory. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionPathsWorkspaceCheckParams -{ - /// Path to check against the session workspace directory. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; - - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} - -/// Resolved location-permissions key and type. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionLocationResolveResult -{ - /// Location key used in the location-permissions store. - [JsonPropertyName("locationKey")] - public string LocationKey { get; set; } = string.Empty; - - /// Whether the location is a git repo or directory. - [JsonPropertyName("locationType")] - public PermissionLocationType LocationType { get; set; } -} - -/// Working directory to resolve into a location-permissions key. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionLocationResolveParams -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; - - /// Working directory whose permission location should be resolved. - [JsonPropertyName("workingDirectory")] - public string WorkingDirectory { get; set; } = string.Empty; -} - -/// Summary of persisted location permissions applied to the session. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionLocationApplyResult -{ - /// Number of persisted allowed directories added to the live path manager. - [JsonPropertyName("appliedDirectoryCount")] - public long AppliedDirectoryCount { get; set; } - - /// Number of location-scoped rules added to the live permission service. - [JsonPropertyName("appliedRuleCount")] - public long AppliedRuleCount { get; set; } - - /// Location-scoped rules applied to the live permission service. - [JsonPropertyName("appliedRules")] - public IList AppliedRules { get => field ??= []; set; } - - /// Whether a different location was applied since the previous apply call. - [JsonPropertyName("changed")] - public bool Changed { get; set; } - - /// Location key used in the location-permissions store. - [JsonPropertyName("locationKey")] - public string LocationKey { get; set; } = string.Empty; - - /// Whether the location is a git repo or directory. - [JsonPropertyName("locationType")] - public PermissionLocationType LocationType { get; set; } -} - -/// Working directory to load persisted location permissions for. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionLocationApplyParams -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; - - /// Working directory whose persisted location permissions should be applied. - [JsonPropertyName("workingDirectory")] - public string WorkingDirectory { get; set; } = string.Empty; -} - -/// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionsLocationsAddToolApprovalResult -{ - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } -} - -/// Tool approval to persist and apply. -/// Polymorphic base type discriminated by kind. -[Experimental(Diagnostics.Experimental)] -[JsonPolymorphic( - TypeDiscriminatorPropertyName = "kind", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsCommands), "commands")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsRead), "read")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsWrite), "write")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsMcp), "mcp")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsMcpSampling), "mcp-sampling")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsMemory), "memory")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsCustomTool), "custom-tool")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsExtensionManagement), "extension-management")] -[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsExtensionPermissionAccess), "extension-permission-access")] -public partial class PermissionsLocationsAddToolApprovalDetails -{ - /// The type discriminator. - [JsonPropertyName("kind")] - public virtual string Kind { get; set; } = string.Empty; -} - - -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsCommands` type. -/// The commands variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsCommands : PermissionsLocationsAddToolApprovalDetails -{ - /// - [JsonIgnore] - public override string Kind => "commands"; - - /// Command identifiers covered by this approval. - [JsonPropertyName("commandIdentifiers")] - public required IList CommandIdentifiers { get; set; } -} - -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsRead` type. -/// The read variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsRead : PermissionsLocationsAddToolApprovalDetails -{ - /// - [JsonIgnore] - public override string Kind => "read"; -} - -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsWrite` type. -/// The write variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsWrite : PermissionsLocationsAddToolApprovalDetails -{ - /// - [JsonIgnore] - public override string Kind => "write"; -} - -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsMcp` type. -/// The mcp variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsMcp : PermissionsLocationsAddToolApprovalDetails -{ - /// - [JsonIgnore] - public override string Kind => "mcp"; - - /// MCP server name. - [JsonPropertyName("serverName")] - public required string ServerName { get; set; } - - /// MCP tool name, or null to cover every tool on the server. - [JsonPropertyName("toolName")] - public string? ToolName { get; set; } + public bool Success { get; set; } } -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsMcpSampling` type. -/// The mcp-sampling variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsMcpSampling : PermissionsLocationsAddToolApprovalDetails +/// Notification payload describing the permission prompt that the client just rendered. +internal sealed class PermissionPromptShownNotification { - /// - [JsonIgnore] - public override string Kind => "mcp-sampling"; + /// Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; - /// MCP server name. - [JsonPropertyName("serverName")] - public required string ServerName { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsMemory` type. -/// The memory variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsMemory : PermissionsLocationsAddToolApprovalDetails +/// Snapshot of the session's allow-listed directories and primary working directory. +public sealed class PermissionPathsList { - /// - [JsonIgnore] - public override string Kind => "memory"; + /// All directories currently allowed for tool access on this session. + [JsonPropertyName("directories")] + public IList Directories { get => field ??= []; set; } + + /// The primary working directory for this session. + [JsonPropertyName("primary")] + public string Primary { get; set; } = string.Empty; } -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsCustomTool` type. -/// The custom-tool variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsCustomTool : PermissionsLocationsAddToolApprovalDetails +/// No parameters; returns the session's allow-listed directories. +internal sealed class PermissionsPathsListRequest { - /// - [JsonIgnore] - public override string Kind => "custom-tool"; - - /// Custom tool name. - [JsonPropertyName("toolName")] - public required string ToolName { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsExtensionManagement` type. -/// The extension-management variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsExtensionManagement : PermissionsLocationsAddToolApprovalDetails +/// Indicates whether the operation succeeded. +public sealed class PermissionsPathsAddResult { - /// - [JsonIgnore] - public override string Kind => "extension-management"; - - /// Optional operation identifier; when omitted, the approval covers all extension management operations. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("operation")] - public string? Operation { get; set; } + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } } -/// Schema for the `PermissionsLocationsAddToolApprovalDetailsExtensionPermissionAccess` type. -/// The extension-permission-access variant of . -[Experimental(Diagnostics.Experimental)] -public partial class PermissionsLocationsAddToolApprovalDetailsExtensionPermissionAccess : PermissionsLocationsAddToolApprovalDetails +/// Directory path to add to the session's allowed directories. +internal sealed class PermissionPathsAddParams { - /// - [JsonIgnore] - public override string Kind => "extension-permission-access"; + /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; - /// Extension name. - [JsonPropertyName("extensionName")] - public required string ExtensionName { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Location-scoped tool approval to persist. -[Experimental(Diagnostics.Experimental)] -internal sealed class PermissionLocationAddToolApprovalParams +/// Indicates whether the operation succeeded. +public sealed class PermissionsPathsUpdatePrimaryResult { - /// Tool approval to persist and apply. - [JsonPropertyName("approval")] - public PermissionsLocationsAddToolApprovalDetails Approval { get => field ??= new(); set; } + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Location key (git root or cwd) to persist the approval to. - [JsonPropertyName("locationKey")] - public string LocationKey { get; set; } = string.Empty; +/// Directory path to set as the session's new primary working directory. +internal sealed class PermissionPathsUpdatePrimaryParams +{ + /// Directory to set as the new primary working directory for the session's permission policy. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Folder trust check result. -[Experimental(Diagnostics.Experimental)] -public sealed class FolderTrustCheckResult +/// Indicates whether the supplied path is within the session's allowed directories. +public sealed class PermissionPathsAllowedCheckResult { - /// Whether the folder is trusted. - [JsonPropertyName("trusted")] - public bool Trusted { get; set; } + /// Whether the path is within the session's allowed directories. + [JsonPropertyName("allowed")] + public bool Allowed { get; set; } } -/// Folder path to check for trust. -[Experimental(Diagnostics.Experimental)] -internal sealed class FolderTrustCheckParams +/// Path to evaluate against the session's allowed directories. +internal sealed class PermissionPathsAllowedCheckParams { - /// Folder path to check. + /// Path to check against the session's allowed directories. [JsonPropertyName("path")] public string Path { get; set; } = string.Empty; @@ -5799,20 +5227,18 @@ internal sealed class FolderTrustCheckParams public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionsFolderTrustAddTrustedResult +/// Indicates whether the supplied path is within the session's workspace directory. +public sealed class PermissionPathsWorkspaceCheckResult { - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// Whether the path is within the session workspace directory. + [JsonPropertyName("allowed")] + public bool Allowed { get; set; } } -/// Folder path to add to trusted folders. -[Experimental(Diagnostics.Experimental)] -internal sealed class FolderTrustAddParams +/// Path to evaluate against the session's workspace (primary) directory. +internal sealed class PermissionPathsWorkspaceCheckParams { - /// Folder path to mark as trusted. + /// Path to check against the session workspace directory. [JsonPropertyName("path")] public string Path { get; set; } = string.Empty; @@ -5822,7 +5248,6 @@ internal sealed class FolderTrustAddParams } /// Indicates whether the operation succeeded. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsUrlsSetUnrestrictedModeResult { /// Whether the operation succeeded. @@ -5831,7 +5256,6 @@ public sealed class PermissionsUrlsSetUnrestrictedModeResult } /// Whether the URL-permission policy should run in unrestricted mode. -[Experimental(Diagnostics.Experimental)] internal sealed class PermissionUrlsSetUnrestrictedModeParams { /// Whether to allow access to all URLs without prompting. Toggles the runtime's URL-permission policy in place. @@ -5902,13 +5326,11 @@ public sealed class SessionMetadataSnapshotWorkspace /// Repository host type, if known. [JsonPropertyName("host_type")] - public WorkspaceSummaryHostType? HostType { get; set; } + public SessionMetadataSnapshotWorkspaceHostType? HostType { get; set; } /// Workspace identifier (1:1 with sessionId). - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] - [MinLength(1)] [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + public Guid Id { get; set; } /// Display name for the session, if set. [JsonPropertyName("name")] @@ -6186,7 +5608,6 @@ internal sealed class MetadataRecomputeContextTokensRequest } /// Identifier of the spawned process, used to correlate streamed output and exit notifications. -[Experimental(Diagnostics.Experimental)] public sealed class ShellExecResult { /// Unique identifier for tracking streamed output. @@ -6195,7 +5616,6 @@ public sealed class ShellExecResult } /// Shell command to run, with optional working directory and timeout in milliseconds. -[Experimental(Diagnostics.Experimental)] internal sealed class ShellExecRequest { /// Shell command to execute. @@ -6217,7 +5637,6 @@ internal sealed class ShellExecRequest } /// Indicates whether the signal was delivered; false if the process was unknown or already exited. -[Experimental(Diagnostics.Experimental)] public sealed class ShellKillResult { /// Whether the signal was sent successfully. @@ -6226,7 +5645,6 @@ public sealed class ShellKillResult } /// Identifier of a process previously returned by "shell.exec" and the signal to send. -[Experimental(Diagnostics.Experimental)] internal sealed class ShellKillRequest { /// Process identifier returned by shell.exec. @@ -7170,13 +6588,13 @@ public ModelPickerCategory(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Lightweight model category optimized for faster, lower-cost interactions. + /// Gets the lightweight value. public static ModelPickerCategory Lightweight { get; } = new("lightweight"); - /// Versatile model category suitable for a broad range of tasks. + /// Gets the versatile value. public static ModelPickerCategory Versatile { get; } = new("versatile"); - /// Powerful model category optimized for complex tasks. + /// Gets the powerful value. public static ModelPickerCategory Powerful { get; } = new("powerful"); /// Returns a value indicating whether two instances are equivalent. @@ -7235,16 +6653,16 @@ public ModelPickerPriceCategory(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Lowest relative token cost tier. + /// Gets the low value. public static ModelPickerPriceCategory Low { get; } = new("low"); - /// Medium relative token cost tier. + /// Gets the medium value. public static ModelPickerPriceCategory Medium { get; } = new("medium"); - /// High relative token cost tier. + /// Gets the high value. public static ModelPickerPriceCategory High { get; } = new("high"); - /// Highest relative token cost tier. + /// Gets the very_high value. public static ModelPickerPriceCategory VeryHigh { get; } = new("very_high"); /// Returns a value indicating whether two instances are equivalent. @@ -7303,13 +6721,13 @@ public ModelPolicyState(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The model is enabled by policy. + /// Gets the enabled value. public static ModelPolicyState Enabled { get; } = new("enabled"); - /// The model is disabled by policy. + /// Gets the disabled value. public static ModelPolicyState Disabled { get; } = new("disabled"); - /// No explicit policy is configured for the model. + /// Gets the unconfigured value. public static ModelPolicyState Unconfigured { get; } = new("unconfigured"); /// Returns a value indicating whether two instances are equivalent. @@ -7368,16 +6786,16 @@ public DiscoveredMcpServerType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Server communicates over stdio with a local child process. + /// Gets the stdio value. public static DiscoveredMcpServerType Stdio { get; } = new("stdio"); - /// Server communicates over streamable HTTP. + /// Gets the http value. public static DiscoveredMcpServerType Http { get; } = new("http"); - /// Server communicates over Server-Sent Events. + /// Gets the sse value. public static DiscoveredMcpServerType Sse { get; } = new("sse"); - /// Server is backed by an in-memory runtime implementation. + /// Gets the memory value. public static DiscoveredMcpServerType Memory { get; } = new("memory"); /// Returns a value indicating whether two instances are equivalent. @@ -7436,10 +6854,10 @@ public SessionFsSetProviderConventions(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Paths use Windows path conventions. + /// Gets the windows value. public static SessionFsSetProviderConventions Windows { get; } = new("windows"); - /// Paths use POSIX path conventions. + /// Gets the posix value. public static SessionFsSetProviderConventions Posix { get; } = new("posix"); /// Returns a value indicating whether two instances are equivalent. @@ -7499,10 +6917,10 @@ public ConnectedRemoteSessionMetadataKind(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Remote CLI session. + /// Gets the remote-session value. public static ConnectedRemoteSessionMetadataKind RemoteSession { get; } = new("remote-session"); - /// GitHub Copilot coding agent session. + /// Gets the coding-agent value. public static ConnectedRemoteSessionMetadataKind CodingAgent { get; } = new("coding-agent"); /// Returns a value indicating whether two instances are equivalent. @@ -7562,10 +6980,10 @@ public SessionContextHostType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Session repository is hosted on GitHub. + /// Gets the github value. public static SessionContextHostType Github { get; } = new("github"); - /// Session repository is hosted on Azure DevOps. + /// Gets the ado value. public static SessionContextHostType Ado { get; } = new("ado"); /// Returns a value indicating whether two instances are equivalent. @@ -7606,7 +7024,6 @@ public override void Write(Utf8JsonWriter writer, SessionContextHostType value, /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SendAgentMode : IEquatable @@ -7625,16 +7042,16 @@ public SendAgentMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The agent is responding interactively to the user. + /// Gets the interactive value. public static SendAgentMode Interactive { get; } = new("interactive"); - /// The agent is preparing a plan before making changes. + /// Gets the plan value. public static SendAgentMode Plan { get; } = new("plan"); - /// The agent is working autonomously toward task completion. + /// Gets the autopilot value. public static SendAgentMode Autopilot { get; } = new("autopilot"); - /// The agent is in shell-focused UI mode. + /// Gets the shell value. public static SendAgentMode Shell { get; } = new("shell"); /// Returns a value indicating whether two instances are equivalent. @@ -7675,7 +7092,6 @@ public override void Write(Utf8JsonWriter writer, SendAgentMode value, JsonSeria /// Type of GitHub reference. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SendAttachmentGithubReferenceType : IEquatable @@ -7694,13 +7110,13 @@ public SendAttachmentGithubReferenceType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// GitHub issue reference. + /// Gets the issue value. public static SendAttachmentGithubReferenceType Issue { get; } = new("issue"); - /// GitHub pull request reference. + /// Gets the pr value. public static SendAttachmentGithubReferenceType Pr { get; } = new("pr"); - /// GitHub discussion reference. + /// Gets the discussion value. public static SendAttachmentGithubReferenceType Discussion { get; } = new("discussion"); /// Returns a value indicating whether two instances are equivalent. @@ -7741,7 +7157,6 @@ public override void Write(Utf8JsonWriter writer, SendAttachmentGithubReferenceT /// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SendMode : IEquatable @@ -7760,10 +7175,10 @@ public SendMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Append the message to the normal session queue. + /// Gets the enqueue value. public static SendMode Enqueue { get; } = new("enqueue"); - /// Interject the message during the in-progress turn. + /// Gets the immediate value. public static SendMode Immediate { get; } = new("immediate"); /// Returns a value indicating whether two instances are equivalent. @@ -7804,7 +7219,6 @@ public override void Write(Utf8JsonWriter writer, SendMode value, JsonSerializer /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SessionLogLevel : IEquatable @@ -7823,13 +7237,13 @@ public SessionLogLevel(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Informational message. + /// Gets the info value. public static SessionLogLevel Info { get; } = new("info"); - /// Warning message that may require attention. + /// Gets the warning value. public static SessionLogLevel Warning { get; } = new("warning"); - /// Error message describing a failure. + /// Gets the error value. public static SessionLogLevel Error { get; } = new("error"); /// Returns a value indicating whether two instances are equivalent. @@ -7870,7 +7284,6 @@ public override void Write(Utf8JsonWriter writer, SessionLogLevel value, JsonSer /// Authentication type. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct AuthInfoType : IEquatable @@ -7889,25 +7302,25 @@ public AuthInfoType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Authentication provided by a GitHub App HMAC credential. + /// Gets the hmac value. public static AuthInfoType Hmac { get; } = new("hmac"); - /// Authentication resolved from environment-provided credentials. + /// Gets the env value. public static AuthInfoType Env { get; } = new("env"); - /// Authentication from an interactive user sign-in. + /// Gets the user value. public static AuthInfoType User { get; } = new("user"); - /// Authentication delegated to the GitHub CLI. + /// Gets the gh-cli value. public static AuthInfoType GhCli { get; } = new("gh-cli"); - /// Authentication from an API key credential. + /// Gets the api-key value. public static AuthInfoType ApiKey { get; } = new("api-key"); - /// Authentication from a GitHub token. + /// Gets the token value. public static AuthInfoType Token { get; } = new("token"); - /// Authentication from a Copilot API token. + /// Gets the copilot-api-token value. public static AuthInfoType CopilotApiToken { get; } = new("copilot-api-token"); /// Returns a value indicating whether two instances are equivalent. @@ -7947,43 +7360,42 @@ public override void Write(Utf8JsonWriter writer, AuthInfoType value, JsonSerial } -/// Allowed values for the `WorkspacesWorkspaceDetailsHostType` enumeration. -[Experimental(Diagnostics.Experimental)] +/// Defines the allowed values. [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] -public readonly struct WorkspacesWorkspaceDetailsHostType : IEquatable +public readonly struct WorkspacesGetWorkspaceResultWorkspaceHostType : IEquatable { private readonly string? _value; - /// Initializes a new instance of the struct. - /// The value to associate with this . + /// Initializes a new instance of the struct. + /// The value to associate with this . [JsonConstructor] - public WorkspacesWorkspaceDetailsHostType(string value) + public WorkspacesGetWorkspaceResultWorkspaceHostType(string value) { ArgumentException.ThrowIfNullOrWhiteSpace(value); _value = value; } - /// Gets the value associated with this . + /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Workspace repository is hosted on GitHub. - public static WorkspacesWorkspaceDetailsHostType Github { get; } = new("github"); + /// Gets the github value. + public static WorkspacesGetWorkspaceResultWorkspaceHostType Github { get; } = new("github"); - /// Workspace repository is hosted on Azure DevOps. - public static WorkspacesWorkspaceDetailsHostType Ado { get; } = new("ado"); + /// Gets the ado value. + public static WorkspacesGetWorkspaceResultWorkspaceHostType Ado { get; } = new("ado"); - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(WorkspacesWorkspaceDetailsHostType left, WorkspacesWorkspaceDetailsHostType right) => left.Equals(right); + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => left.Equals(right); - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(WorkspacesWorkspaceDetailsHostType left, WorkspacesWorkspaceDetailsHostType right) => !(left == right); + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => !(left == right); /// - public override bool Equals(object? obj) => obj is WorkspacesWorkspaceDetailsHostType other && Equals(other); + public override bool Equals(object? obj) => obj is WorkspacesGetWorkspaceResultWorkspaceHostType other && Equals(other); /// - public bool Equals(WorkspacesWorkspaceDetailsHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + public bool Equals(WorkspacesGetWorkspaceResultWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); /// public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); @@ -7991,27 +7403,26 @@ public WorkspacesWorkspaceDetailsHostType(string value) /// public override string ToString() => Value; - /// Provides a for serializing instances. + /// Provides a for serializing instances. [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter + public sealed class Converter : JsonConverter { /// - public override WorkspacesWorkspaceDetailsHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override WorkspacesGetWorkspaceResultWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// - public override void Write(Utf8JsonWriter writer, WorkspacesWorkspaceDetailsHostType value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, WorkspacesGetWorkspaceResultWorkspaceHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesWorkspaceDetailsHostType)); + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); } } } /// Where this source lives — used for UI grouping. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct InstructionsSourcesLocation : IEquatable @@ -8030,16 +7441,16 @@ public InstructionsSourcesLocation(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Instructions live in user-level configuration. + /// Gets the user value. public static InstructionsSourcesLocation User { get; } = new("user"); - /// Instructions live in repository-level configuration. + /// Gets the repository value. public static InstructionsSourcesLocation Repository { get; } = new("repository"); - /// Instructions live under the current working directory. + /// Gets the working-directory value. public static InstructionsSourcesLocation WorkingDirectory { get; } = new("working-directory"); - /// Instructions live in plugin-provided configuration. + /// Gets the plugin value. public static InstructionsSourcesLocation Plugin { get; } = new("plugin"); /// Returns a value indicating whether two instances are equivalent. @@ -8080,7 +7491,6 @@ public override void Write(Utf8JsonWriter writer, InstructionsSourcesLocation va /// Category of instruction source — used for merge logic. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct InstructionsSourcesType : IEquatable @@ -8099,25 +7509,25 @@ public InstructionsSourcesType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Instructions loaded from the user's home configuration. + /// Gets the home value. public static InstructionsSourcesType Home { get; } = new("home"); - /// Instructions loaded from repository-scoped files. + /// Gets the repo value. public static InstructionsSourcesType Repo { get; } = new("repo"); - /// Instructions loaded from model-specific files. + /// Gets the model value. public static InstructionsSourcesType Model { get; } = new("model"); - /// Instructions loaded from VS Code instruction files. + /// Gets the vscode value. public static InstructionsSourcesType Vscode { get; } = new("vscode"); - /// Instructions discovered from nested agent files. + /// Gets the nested-agents value. public static InstructionsSourcesType NestedAgents { get; } = new("nested-agents"); - /// Instructions inherited from child instruction files. + /// Gets the child-instructions value. public static InstructionsSourcesType ChildInstructions { get; } = new("child-instructions"); - /// Instructions supplied by an installed plugin. + /// Gets the plugin value. public static InstructionsSourcesType Plugin { get; } = new("plugin"); /// Returns a value indicating whether two instances are equivalent. @@ -8177,22 +7587,22 @@ public AgentInfoSource(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Agent loaded from the user's personal agent configuration. + /// Gets the user value. public static AgentInfoSource User { get; } = new("user"); - /// Agent loaded from the current project's repository configuration. + /// Gets the project value. public static AgentInfoSource Project { get; } = new("project"); - /// Agent inherited from a parent project or workspace. + /// Gets the inherited value. public static AgentInfoSource Inherited { get; } = new("inherited"); - /// Agent provided by a remote runtime or service. + /// Gets the remote value. public static AgentInfoSource Remote { get; } = new("remote"); - /// Agent contributed by an installed plugin. + /// Gets the plugin value. public static AgentInfoSource Plugin { get; } = new("plugin"); - /// Agent built into the Copilot runtime. + /// Gets the builtin value. public static AgentInfoSource Builtin { get; } = new("builtin"); /// Returns a value indicating whether two instances are equivalent. @@ -8252,10 +7662,10 @@ public TaskExecutionMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The task was started with synchronous waiting. + /// Gets the sync value. public static TaskExecutionMode Sync { get; } = new("sync"); - /// The task is managed in the background. + /// Gets the background value. public static TaskExecutionMode Background { get; } = new("background"); /// Returns a value indicating whether two instances are equivalent. @@ -8315,19 +7725,19 @@ public TaskStatus(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The task is actively executing. + /// Gets the running value. public static TaskStatus Running { get; } = new("running"); - /// The task is waiting for additional input. + /// Gets the idle value. public static TaskStatus Idle { get; } = new("idle"); - /// The task finished successfully. + /// Gets the completed value. public static TaskStatus Completed { get; } = new("completed"); - /// The task finished with an error. + /// Gets the failed value. public static TaskStatus Failed { get; } = new("failed"); - /// The task was cancelled before completion. + /// Gets the cancelled value. public static TaskStatus Cancelled { get; } = new("cancelled"); /// Returns a value indicating whether two instances are equivalent. @@ -8387,10 +7797,10 @@ public TaskShellInfoAttachmentMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The shell runs in a managed PTY session. + /// Gets the attached value. public static TaskShellInfoAttachmentMode Attached { get; } = new("attached"); - /// The shell runs as an independent background process. + /// Gets the detached value. public static TaskShellInfoAttachmentMode Detached { get; } = new("detached"); /// Returns a value indicating whether two instances are equivalent. @@ -8450,13 +7860,13 @@ public McpSamplingExecutionAction(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The sampling inference completed and produced a result. + /// Gets the success value. public static McpSamplingExecutionAction Success { get; } = new("success"); - /// The sampling inference failed or was rejected. + /// Gets the failure value. public static McpSamplingExecutionAction Failure { get; } = new("failure"); - /// The sampling inference was cancelled before completion. + /// Gets the cancelled value. public static McpSamplingExecutionAction Cancelled { get; } = new("cancelled"); /// Returns a value indicating whether two instances are equivalent. @@ -8516,10 +7926,10 @@ public McpSetEnvValueModeDetails(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Treat MCP server environment values as literal strings. + /// Gets the direct value. public static McpSetEnvValueModeDetails Direct { get; } = new("direct"); - /// Treat MCP server environment values as host-side references to resolve before launch. + /// Gets the indirect value. public static McpSetEnvValueModeDetails Indirect { get; } = new("indirect"); /// Returns a value indicating whether two instances are equivalent. @@ -8579,10 +7989,10 @@ public OptionsUpdateEnvValueMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Pass MCP server environment values as literal strings. + /// Gets the direct value. public static OptionsUpdateEnvValueMode Direct { get; } = new("direct"); - /// Resolve MCP server environment values from host-side references. + /// Gets the indirect value. public static OptionsUpdateEnvValueMode Indirect { get; } = new("indirect"); /// Returns a value indicating whether two instances are equivalent. @@ -8642,10 +8052,10 @@ public ExtensionSource(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Extension discovered from the current project's .github/extensions directory. + /// Gets the project value. public static ExtensionSource Project { get; } = new("project"); - /// Extension discovered from the user's ~/.copilot/extensions directory. + /// Gets the user value. public static ExtensionSource User { get; } = new("user"); /// Returns a value indicating whether two instances are equivalent. @@ -8705,16 +8115,16 @@ public ExtensionStatus(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The extension process is running. + /// Gets the running value. public static ExtensionStatus Running { get; } = new("running"); - /// The extension is installed but disabled. + /// Gets the disabled value. public static ExtensionStatus Disabled { get; } = new("disabled"); - /// The extension failed to start or crashed. + /// Gets the failed value. public static ExtensionStatus Failed { get; } = new("failed"); - /// The extension process is starting. + /// Gets the starting value. public static ExtensionStatus Starting { get; } = new("starting"); /// Returns a value indicating whether two instances are equivalent. @@ -8755,7 +8165,6 @@ public override void Write(Utf8JsonWriter writer, ExtensionStatus value, JsonSer /// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SlashCommandInputCompletion : IEquatable @@ -8774,7 +8183,7 @@ public SlashCommandInputCompletion(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Input should complete filesystem directories. + /// Gets the directory value. public static SlashCommandInputCompletion Directory { get; } = new("directory"); /// Returns a value indicating whether two instances are equivalent. @@ -8815,7 +8224,6 @@ public override void Write(Utf8JsonWriter writer, SlashCommandInputCompletion va /// Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SlashCommandKind : IEquatable @@ -8834,13 +8242,13 @@ public SlashCommandKind(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Command implemented by the runtime. + /// Gets the builtin value. public static SlashCommandKind Builtin { get; } = new("builtin"); - /// Command backed by a skill. + /// Gets the skill value. public static SlashCommandKind Skill { get; } = new("skill"); - /// Command registered by an SDK client or extension. + /// Gets the client value. public static SlashCommandKind Client { get; } = new("client"); /// Returns a value indicating whether two instances are equivalent. @@ -8881,7 +8289,6 @@ public override void Write(Utf8JsonWriter writer, SlashCommandKind value, JsonSe /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct UIElicitationResponseAction : IEquatable @@ -8900,13 +8307,13 @@ public UIElicitationResponseAction(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The user submitted the requested form values. + /// Gets the accept value. public static UIElicitationResponseAction Accept { get; } = new("accept"); - /// The user explicitly declined to provide the requested input. + /// Gets the decline value. public static UIElicitationResponseAction Decline { get; } = new("decline"); - /// The user dismissed the elicitation request. + /// Gets the cancel value. public static UIElicitationResponseAction Cancel { get; } = new("cancel"); /// Returns a value indicating whether two instances are equivalent. @@ -8947,7 +8354,6 @@ public override void Write(Utf8JsonWriter writer, UIElicitationResponseAction va /// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct UIAutoModeSwitchResponse : IEquatable @@ -8966,13 +8372,13 @@ public UIAutoModeSwitchResponse(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Allow the automatic mode switch for this turn. + /// Gets the yes value. public static UIAutoModeSwitchResponse Yes { get; } = new("yes"); - /// Allow this mode switch and persist the preference. + /// Gets the yes_always value. public static UIAutoModeSwitchResponse YesAlways { get; } = new("yes_always"); - /// Decline the automatic mode switch. + /// Gets the no value. public static UIAutoModeSwitchResponse No { get; } = new("no"); /// Returns a value indicating whether two instances are equivalent. @@ -9013,7 +8419,6 @@ public override void Write(Utf8JsonWriter writer, UIAutoModeSwitchResponse value /// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct UIExitPlanModeAction : IEquatable @@ -9032,16 +8437,16 @@ public UIExitPlanModeAction(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Exit plan mode without starting implementation. + /// Gets the exit_only value. public static UIExitPlanModeAction ExitOnly { get; } = new("exit_only"); - /// Exit plan mode and continue interactively. + /// Gets the interactive value. public static UIExitPlanModeAction Interactive { get; } = new("interactive"); - /// Exit plan mode and continue in autopilot mode. + /// Gets the autopilot value. public static UIExitPlanModeAction Autopilot { get; } = new("autopilot"); - /// Exit plan mode and continue in autopilot mode with parallel subagent execution. + /// Gets the autopilot_fleet value. public static UIExitPlanModeAction AutopilotFleet { get; } = new("autopilot_fleet"); /// Returns a value indicating whether two instances are equivalent. @@ -9082,7 +8487,6 @@ public override void Write(Utf8JsonWriter writer, UIExitPlanModeAction value, Js /// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct PermissionsConfigureAdditionalContentExclusionPolicyScope : IEquatable @@ -9101,10 +8505,10 @@ public PermissionsConfigureAdditionalContentExclusionPolicyScope(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The content exclusion policy applies to the current repository. + /// Gets the repo value. public static PermissionsConfigureAdditionalContentExclusionPolicyScope Repo { get; } = new("repo"); - /// The content exclusion policy applies across all repositories. + /// Gets the all value. public static PermissionsConfigureAdditionalContentExclusionPolicyScope All { get; } = new("all"); /// Returns a value indicating whether two instances are equivalent. @@ -9145,7 +8549,6 @@ public override void Write(Utf8JsonWriter writer, PermissionsConfigureAdditional /// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct PermissionsSetApproveAllSource : IEquatable @@ -9164,16 +8567,16 @@ public PermissionsSetApproveAllSource(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Allow-all was enabled from a CLI command-line flag. + /// Gets the cli_flag value. public static PermissionsSetApproveAllSource CliFlag { get; } = new("cli_flag"); - /// Allow-all was enabled by a slash command. + /// Gets the slash_command value. public static PermissionsSetApproveAllSource SlashCommand { get; } = new("slash_command"); - /// Allow-all was enabled by confirming autopilot behavior. + /// Gets the autopilot_confirmation value. public static PermissionsSetApproveAllSource AutopilotConfirmation { get; } = new("autopilot_confirmation"); - /// Allow-all was enabled through an RPC caller. + /// Gets the rpc value. public static PermissionsSetApproveAllSource Rpc { get; } = new("rpc"); /// Returns a value indicating whether two instances are equivalent. @@ -9214,7 +8617,6 @@ public override void Write(Utf8JsonWriter writer, PermissionsSetApproveAllSource /// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct PermissionsModifyRulesScope : IEquatable @@ -9233,10 +8635,10 @@ public PermissionsModifyRulesScope(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Apply the rule change only to this session. + /// Gets the session value. public static PermissionsModifyRulesScope Session { get; } = new("session"); - /// Persist the rule change for this project location. + /// Gets the location value. public static PermissionsModifyRulesScope Location { get; } = new("location"); /// Returns a value indicating whether two instances are equivalent. @@ -9276,69 +8678,6 @@ public override void Write(Utf8JsonWriter writer, PermissionsModifyRulesScope va } -/// Whether the location is a git repo or directory. -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct PermissionLocationType : IEquatable -{ - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public PermissionLocationType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } - - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; - - /// The permission location is persisted at the git repository root. - public static PermissionLocationType Repo { get; } = new("repo"); - - /// The permission location is persisted at the working directory. - public static PermissionLocationType Dir { get; } = new("dir"); - - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(PermissionLocationType left, PermissionLocationType right) => left.Equals(right); - - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(PermissionLocationType left, PermissionLocationType right) => !(left == right); - - /// - public override bool Equals(object? obj) => obj is PermissionLocationType other && Equals(other); - - /// - public bool Equals(PermissionLocationType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); - - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); - - /// - public override string ToString() => Value; - - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override PermissionLocationType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } - - /// - public override void Write(Utf8JsonWriter writer, PermissionLocationType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionLocationType)); - } - } -} - - /// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot'). [Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] @@ -9359,13 +8698,13 @@ public MetadataSnapshotCurrentMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The agent is responding interactively to the user. + /// Gets the interactive value. public static MetadataSnapshotCurrentMode Interactive { get; } = new("interactive"); - /// The agent is preparing a plan before making changes. + /// Gets the plan value. public static MetadataSnapshotCurrentMode Plan { get; } = new("plan"); - /// The agent is working autonomously toward task completion. + /// Gets the autopilot value. public static MetadataSnapshotCurrentMode Autopilot { get; } = new("autopilot"); /// Returns a value indicating whether two instances are equivalent. @@ -9425,10 +8764,10 @@ public MetadataSnapshotRemoteMetadataTaskType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Remote task originated from Copilot Coding Agent. + /// Gets the cca value. public static MetadataSnapshotRemoteMetadataTaskType Cca { get; } = new("cca"); - /// Remote task originated from a CLI remote-session invocation. + /// Gets the cli value. public static MetadataSnapshotRemoteMetadataTaskType Cli { get; } = new("cli"); /// Returns a value indicating whether two instances are equivalent. @@ -9469,42 +8808,41 @@ public override void Write(Utf8JsonWriter writer, MetadataSnapshotRemoteMetadata /// Repository host type, if known. -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] -public readonly struct WorkspaceSummaryHostType : IEquatable +public readonly struct SessionMetadataSnapshotWorkspaceHostType : IEquatable { private readonly string? _value; - /// Initializes a new instance of the struct. - /// The value to associate with this . + /// Initializes a new instance of the struct. + /// The value to associate with this . [JsonConstructor] - public WorkspaceSummaryHostType(string value) + public SessionMetadataSnapshotWorkspaceHostType(string value) { ArgumentException.ThrowIfNullOrWhiteSpace(value); _value = value; } - /// Gets the value associated with this . + /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Workspace summary repository is hosted on GitHub. - public static WorkspaceSummaryHostType Github { get; } = new("github"); + /// Gets the github value. + public static SessionMetadataSnapshotWorkspaceHostType Github { get; } = new("github"); - /// Workspace summary repository is hosted on Azure DevOps. - public static WorkspaceSummaryHostType Ado { get; } = new("ado"); + /// Gets the ado value. + public static SessionMetadataSnapshotWorkspaceHostType Ado { get; } = new("ado"); - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(WorkspaceSummaryHostType left, WorkspaceSummaryHostType right) => left.Equals(right); + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionMetadataSnapshotWorkspaceHostType left, SessionMetadataSnapshotWorkspaceHostType right) => left.Equals(right); - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(WorkspaceSummaryHostType left, WorkspaceSummaryHostType right) => !(left == right); + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionMetadataSnapshotWorkspaceHostType left, SessionMetadataSnapshotWorkspaceHostType right) => !(left == right); /// - public override bool Equals(object? obj) => obj is WorkspaceSummaryHostType other && Equals(other); + public override bool Equals(object? obj) => obj is SessionMetadataSnapshotWorkspaceHostType other && Equals(other); /// - public bool Equals(WorkspaceSummaryHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + public bool Equals(SessionMetadataSnapshotWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); /// public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); @@ -9512,20 +8850,20 @@ public WorkspaceSummaryHostType(string value) /// public override string ToString() => Value; - /// Provides a for serializing instances. + /// Provides a for serializing instances. [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter + public sealed class Converter : JsonConverter { /// - public override WorkspaceSummaryHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override SessionMetadataSnapshotWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// - public override void Write(Utf8JsonWriter writer, WorkspaceSummaryHostType value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, SessionMetadataSnapshotWorkspaceHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspaceSummaryHostType)); + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); } } } @@ -9551,10 +8889,10 @@ public SessionWorkingDirectoryContextHostType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The working directory repository is hosted on GitHub. + /// Gets the github value. public static SessionWorkingDirectoryContextHostType Github { get; } = new("github"); - /// The working directory repository is hosted on Azure DevOps. + /// Gets the ado value. public static SessionWorkingDirectoryContextHostType Ado { get; } = new("ado"); /// Returns a value indicating whether two instances are equivalent. @@ -9595,7 +8933,6 @@ public override void Write(Utf8JsonWriter writer, SessionWorkingDirectoryContext /// Signal to send (default: SIGTERM). -[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct ShellKillSignal : IEquatable @@ -9614,13 +8951,13 @@ public ShellKillSignal(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Request graceful process termination. + /// Gets the SIGTERM value. public static ShellKillSignal SIGTERM { get; } = new("SIGTERM"); - /// Forcefully terminate the process. + /// Gets the SIGKILL value. public static ShellKillSignal SIGKILL { get; } = new("SIGKILL"); - /// Send an interrupt signal to the process. + /// Gets the SIGINT value. public static ShellKillSignal SIGINT { get; } = new("SIGINT"); /// Returns a value indicating whether two instances are equivalent. @@ -9680,10 +9017,10 @@ public QueuePendingItemsKind(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// A queued user message. + /// Gets the message value. public static QueuePendingItemsKind Message { get; } = new("message"); - /// A queued slash command or model-change command. + /// Gets the command value. public static QueuePendingItemsKind Command { get; } = new("command"); /// Returns a value indicating whether two instances are equivalent. @@ -9743,10 +9080,10 @@ public EventsCursorStatus(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The cursor was applied successfully. + /// Gets the ok value. public static EventsCursorStatus Ok { get; } = new("ok"); - /// The cursor referred to history that is no longer available. + /// Gets the expired value. public static EventsCursorStatus Expired { get; } = new("expired"); /// Returns a value indicating whether two instances are equivalent. @@ -9806,10 +9143,10 @@ public EventsAgentScope(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Return main-agent events and typed subagent lifecycle events. + /// Gets the primary value. public static EventsAgentScope Primary { get; } = new("primary"); - /// Return events from all agents. + /// Gets the all value. public static EventsAgentScope All { get; } = new("all"); /// Returns a value indicating whether two instances are equivalent. @@ -9869,13 +9206,13 @@ public RemoteSessionMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Disable remote session export and steering. + /// Gets the off value. public static RemoteSessionMode Off { get; } = new("off"); - /// Export session events to GitHub without enabling remote steering. + /// Gets the export value. public static RemoteSessionMode Export { get; } = new("export"); - /// Enable both remote session export and remote steering. + /// Gets the on value. public static RemoteSessionMode On { get; } = new("on"); /// Returns a value indicating whether two instances are equivalent. @@ -9934,10 +9271,10 @@ public SessionFsErrorCode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The requested path does not exist. + /// Gets the ENOENT value. public static SessionFsErrorCode ENOENT { get; } = new("ENOENT"); - /// The filesystem operation failed for an unspecified reason. + /// Gets the UNKNOWN value. public static SessionFsErrorCode UNKNOWN { get; } = new("UNKNOWN"); /// Returns a value indicating whether two instances are equivalent. @@ -9996,10 +9333,10 @@ public SessionFsReaddirWithTypesEntryType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// The entry is a file. + /// Gets the file value. public static SessionFsReaddirWithTypesEntryType File { get; } = new("file"); - /// The entry is a directory. + /// Gets the directory value. public static SessionFsReaddirWithTypesEntryType Directory { get; } = new("directory"); /// Returns a value indicating whether two instances are equivalent. @@ -10058,13 +9395,13 @@ public SessionFsSqliteQueryType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Execute DDL or multi-statement SQL without returning rows. + /// Gets the exec value. public static SessionFsSqliteQueryType Exec { get; } = new("exec"); - /// Execute a SELECT-style query and return rows. + /// Gets the query value. public static SessionFsSqliteQueryType Query { get; } = new("query"); - /// Execute INSERT, UPDATE, or DELETE SQL and return affected-row metadata. + /// Gets the run value. public static SessionFsSqliteQueryType Run { get; } = new("run"); /// Returns a value indicating whether two instances are equivalent. @@ -10464,7 +9801,7 @@ public async Task ConnectAsync(string sessionId, /// Optional filter applied to the returned sessions. /// The to monitor for cancellation requests. The default is . /// Persisted sessions matching the filter, ordered most-recently-modified first. - public async Task ListAsync(long? metadataLimit = null, SessionListFilter? filter = null, CancellationToken cancellationToken = default) + public async Task ListAsync(long? metadataLimit = null, SessionsListRequestFilter? filter = null, CancellationToken cancellationToken = default) { var request = new SessionsListRequest { MetadataLimit = metadataLimit, Filter = filter }; return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.list", [request], cancellationToken); @@ -10847,7 +10184,6 @@ internal SessionRpc(CopilotSession session) /// Suspends the session while preserving persisted state for later resume. /// The to monitor for cancellation requests. The default is . - [Experimental(Diagnostics.Experimental)] public async Task SuspendAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -10872,7 +10208,6 @@ public async Task SuspendAsync(CancellationToken cancellationToken = default) /// If true, await completion of the agentic loop for this message before returning. Defaults to false (fire-and-forget). When true, the result still contains the same `messageId`; the caller can rely on the agent having processed the message before the call resolves. /// The to monitor for cancellation requests. The default is . /// Result of sending a user message. - [Experimental(Diagnostics.Experimental)] public async Task SendAsync(string prompt, string? displayPrompt = null, IList? attachments = null, SendMode? mode = null, bool? prepend = null, bool? billable = null, string? requiredTool = null, object? source = null, SendAgentMode? agentMode = null, IDictionary? requestHeaders = null, string? traceparent = null, string? tracestate = null, bool? wait = null, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(prompt); @@ -10886,7 +10221,6 @@ public async Task SendAsync(string prompt, string? displayPrompt = n /// Finite reason code describing why the current turn was aborted. /// The to monitor for cancellation requests. The default is . /// Result of aborting the current turn. - [Experimental(Diagnostics.Experimental)] public async Task AbortAsync(AbortReason? reason = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -10899,7 +10233,6 @@ public async Task AbortAsync(AbortReason? reason = null, Cancellati /// Why the session is being shut down. Defaults to "routine" when omitted. /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. /// The to monitor for cancellation requests. The default is . - [Experimental(Diagnostics.Experimental)] public async Task ShutdownAsync(ShutdownType? type = null, string? reason = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -10917,7 +10250,6 @@ public async Task ShutdownAsync(ShutdownType? type = null, string? reason = null /// Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. /// The to monitor for cancellation requests. The default is . /// Identifier of the session event that was emitted for the log message. - [Experimental(Diagnostics.Experimental)] public async Task LogAsync(string message, SessionLogLevel? level = null, string? type = null, bool? ephemeral = null, string? url = null, string? tip = null, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(message); @@ -10929,7 +10261,6 @@ public async Task LogAsync(string message, SessionLogLevel? level = n } /// Provides session-scoped Auth APIs. -[Experimental(Diagnostics.Experimental)] public sealed class AuthApi { private readonly CopilotSession _session; @@ -10964,7 +10295,6 @@ public async Task SetCredentialsAsync(AuthInfo? cre } /// Provides session-scoped Model APIs. -[Experimental(Diagnostics.Experimental)] public sealed class ModelApi { private readonly CopilotSession _session; @@ -11016,7 +10346,6 @@ public async Task SetReasoningEffortAsync(string } /// Provides session-scoped Mode APIs. -[Experimental(Diagnostics.Experimental)] public sealed class ModeApi { private readonly CopilotSession _session; @@ -11050,7 +10379,6 @@ public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken } /// Provides session-scoped Name APIs. -[Experimental(Diagnostics.Experimental)] public sealed class NameApi { private readonly CopilotSession _session; @@ -11098,7 +10426,6 @@ public async Task SetAutoAsync(string summary, CancellationTo } /// Provides session-scoped Plan APIs. -[Experimental(Diagnostics.Experimental)] public sealed class PlanApi { private readonly CopilotSession _session; @@ -11143,7 +10470,6 @@ public async Task DeleteAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Workspaces APIs. -[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesApi { private readonly CopilotSession _session; @@ -11240,7 +10566,6 @@ public async Task SaveLargePasteAsync(string con } /// Provides session-scoped Instructions APIs. -[Experimental(Diagnostics.Experimental)] public sealed class InstructionsApi { private readonly CopilotSession _session; @@ -11898,7 +11223,6 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Tools APIs. -[Experimental(Diagnostics.Experimental)] public sealed class ToolsApi { private readonly CopilotSession _session; @@ -11936,7 +11260,6 @@ public async Task InitializeAndValidateAsync(C } /// Provides session-scoped Commands APIs. -[Experimental(Diagnostics.Experimental)] public sealed class CommandsApi { private readonly CopilotSession _session; @@ -12055,7 +11378,6 @@ public async Task SetFeatureOverridesAsync(IDictionary features, } /// Provides session-scoped Ui APIs. -[Experimental(Diagnostics.Experimental)] public sealed class UiApi { private readonly CopilotSession _session; @@ -12179,7 +11501,6 @@ public async Task UnregisterDirec } /// Provides session-scoped Permissions APIs. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsApi { private readonly CopilotSession _session; @@ -12302,18 +11623,6 @@ public async Task NotifyPromptShownAsync(str Interlocked.CompareExchange(ref field, new(_session), null) ?? field; - /// Locations APIs. - public PermissionsLocationsApi Locations => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; - - /// FolderTrust APIs. - public PermissionsFolderTrustApi FolderTrust => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; - /// Urls APIs. public PermissionsUrlsApi Urls => field ?? @@ -12322,7 +11631,6 @@ public async Task NotifyPromptShownAsync(str } /// Provides session-scoped PermissionsPaths APIs. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsPathsApi { private readonly CopilotSession _session; @@ -12396,99 +11704,7 @@ public async Task IsPathWithinWorkspaceAsyn } } -/// Provides session-scoped PermissionsLocations APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionsLocationsApi -{ - private readonly CopilotSession _session; - - internal PermissionsLocationsApi(CopilotSession session) - { - _session = session; - } - - /// Resolves the permission location key and type for a working directory. - /// Working directory whose permission location should be resolved. - /// The to monitor for cancellation requests. The default is . - /// Resolved location-permissions key and type. - public async Task ResolveAsync(string workingDirectory, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(workingDirectory); - _session.ThrowIfDisposed(); - - var request = new PermissionLocationResolveParams { SessionId = _session.SessionId, WorkingDirectory = workingDirectory }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.locations.resolve", [request], cancellationToken); - } - - /// Applies persisted location-scoped tool approvals and allowed directories for a working directory to this session's permission service. - /// Working directory whose persisted location permissions should be applied. - /// The to monitor for cancellation requests. The default is . - /// Summary of persisted location permissions applied to the session. - public async Task ApplyAsync(string workingDirectory, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(workingDirectory); - _session.ThrowIfDisposed(); - - var request = new PermissionLocationApplyParams { SessionId = _session.SessionId, WorkingDirectory = workingDirectory }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.locations.apply", [request], cancellationToken); - } - - /// Persists a tool approval for a permission location and applies its rules to this session's live permission service. - /// Location key (git root or cwd) to persist the approval to. - /// Tool approval to persist and apply. - /// The to monitor for cancellation requests. The default is . - /// Indicates whether the operation succeeded. - public async Task AddToolApprovalAsync(string locationKey, PermissionsLocationsAddToolApprovalDetails approval, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(locationKey); - ArgumentNullException.ThrowIfNull(approval); - _session.ThrowIfDisposed(); - - var request = new PermissionLocationAddToolApprovalParams { SessionId = _session.SessionId, LocationKey = locationKey, Approval = approval }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.locations.addToolApproval", [request], cancellationToken); - } -} - -/// Provides session-scoped PermissionsFolderTrust APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class PermissionsFolderTrustApi -{ - private readonly CopilotSession _session; - - internal PermissionsFolderTrustApi(CopilotSession session) - { - _session = session; - } - - /// Reports whether a folder is trusted according to the user's folder trust state. - /// Folder path to check. - /// The to monitor for cancellation requests. The default is . - /// Folder trust check result. - public async Task IsTrustedAsync(string path, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(path); - _session.ThrowIfDisposed(); - - var request = new FolderTrustCheckParams { SessionId = _session.SessionId, Path = path }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.folderTrust.isTrusted", [request], cancellationToken); - } - - /// Adds a folder to the user's trusted folders list. - /// Folder path to mark as trusted. - /// The to monitor for cancellation requests. The default is . - /// Indicates whether the operation succeeded. - public async Task AddTrustedAsync(string path, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(path); - _session.ThrowIfDisposed(); - - var request = new FolderTrustAddParams { SessionId = _session.SessionId, Path = path }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.folderTrust.addTrusted", [request], cancellationToken); - } -} - /// Provides session-scoped PermissionsUrls APIs. -[Experimental(Diagnostics.Experimental)] public sealed class PermissionsUrlsApi { private readonly CopilotSession _session; @@ -12599,7 +11815,6 @@ public async Task RecomputeContextTokensAs } /// Provides session-scoped Shell APIs. -[Experimental(Diagnostics.Experimental)] public sealed class ShellApi { private readonly CopilotSession _session; @@ -13354,9 +12569,6 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func(), + ToolTelemetry = new Dictionary(), }, SuppressOutput = false, }); From 25db93aba91e47aaa4b3f44194036d2b8d860d9b Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 18:02:19 +0100 Subject: [PATCH 21/40] Revert "Fix MCP config serialization" This reverts commit 50540ac1f381d8bcf8544b3808c142d836454668. --- dotnet/src/Types.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index f125abc1a..fa26a9106 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -1908,7 +1908,6 @@ private protected McpServerConfig() { } /// Optional timeout in milliseconds for tool calls to this server. /// [JsonPropertyName("timeout")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public int? Timeout { get; set; } } @@ -1937,14 +1936,12 @@ public sealed class McpStdioServerConfig : McpServerConfig /// Environment variables to pass to the server. /// [JsonPropertyName("env")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IDictionary? Env { get; set; } /// /// Working directory for the server process. /// [JsonPropertyName("cwd")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? WorkingDirectory { get; set; } } @@ -1967,28 +1964,24 @@ public sealed class McpHttpServerConfig : McpServerConfig /// Optional HTTP headers to include in requests. /// [JsonPropertyName("headers")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IDictionary? Headers { get; set; } /// /// Optional OAuth client ID for the remote server. /// [JsonPropertyName("oauthClientId")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? OauthClientId { get; set; } /// /// Whether this is a public OAuth client. /// [JsonPropertyName("oauthPublicClient")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? OauthPublicClient { get; set; } /// /// Optional OAuth grant type for the remote server. /// [JsonPropertyName("oauthGrantType")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public McpHttpServerConfigOauthGrantType? OauthGrantType { get; set; } } From ae49e16e8ea19d0fab413616d993a33bce0e59bf Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 18:26:18 +0100 Subject: [PATCH 22/40] Fixes to E2E tests to restore main behavior --- dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs | 2 +- dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs | 4 ++-- dotnet/test/Harness/E2ETestContext.cs | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs index ff134f50f..b353b97ae 100644 --- a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs +++ b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs @@ -57,7 +57,7 @@ private CopilotClient CreateExtensionsClient() { return Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(args: ["--yolo"]), + Connection = RuntimeConnection.Stdio(args: ["--yolo"]), Environment = ExtensionsEnabledEnvironment(), }); } diff --git a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs index 2116eedd1..f7a1bf574 100644 --- a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs @@ -102,7 +102,7 @@ public async Task Should_List_Extensions() // preventing breakage from new gates (e.g., extension-permission-access). await using var yoloClient = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(args: ["--yolo"]), + Connection = RuntimeConnection.Stdio(args: ["--yolo"]), }); await using var session = await yoloClient.CreateSessionAsync(new SessionConfig { @@ -188,7 +188,7 @@ public async Task Should_Report_Error_When_Extensions_Are_Not_Available() // preventing breakage from new gates (e.g., extension-permission-access). await using var yoloClient = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(args: ["--yolo"]), + Connection = RuntimeConnection.Stdio(args: ["--yolo"]), }); await using var session = await yoloClient.CreateSessionAsync(new SessionConfig { diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index afd031bbc..ea28516dd 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -221,15 +221,14 @@ public CopilotClient CreateClient( options.Logger ??= Logger; // Build the connection. If the caller supplied one, just ensure the runtime path is set; - // otherwise default to Tcp with bundled CLI path (matches the previous "useStdio: false, - // CliPath = bundled" behavior). + // otherwise default to Stdio with the bundled runtime (matches CopilotClient's own default). var cliPath = GetCliPath(_repoRoot); switch (options.Connection) { case null: - options.Connection = useStdio == true - ? RuntimeConnection.Stdio(path: cliPath) - : RuntimeConnection.Tcp(path: cliPath); + options.Connection = useStdio == false + ? RuntimeConnection.Tcp(path: cliPath) + : RuntimeConnection.Stdio(path: cliPath); break; case ChildProcessRuntimeConnection child when child.Path is null: child.Path = cliPath; From 2b65212d669de06723f40af54818de3d866fe49b Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 18:40:49 +0100 Subject: [PATCH 23/40] Restore TCP transport for two ClientOptions tests Phase 9 bulk replace mapped 'CliPath = ..., CliArgs = [...]' to RuntimeConnection.Stdio without noticing the surrounding Ctx.CreateClient(useStdio: false, ...) on the outer argument list. On main these tests intentionally span the fake CLI as a TCP server. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/E2E/ClientOptionsE2ETests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index 3906b1d5e..15c07b58c 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -230,7 +230,7 @@ public async Task ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup() useStdio: false, options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath), + Connection = RuntimeConnection.Tcp(path: cliPath), UseLoggedInUser = false, }); @@ -252,7 +252,7 @@ public async Task StartAsync_Cleans_Up_Tcp_Cli_Process_When_Connect_Fails() useStdio: false, options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)]), + Connection = RuntimeConnection.Tcp(path: cliPath, args: ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)]), UseLoggedInUser = false, }); From dd9a270586d1d9d96f9d4d1f42ddf0ea00ca15b1 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 18:44:02 +0100 Subject: [PATCH 24/40] Test harness: throw if both useStdio and Connection are supplied When a caller passes both, intent is ambiguous and easy to get wrong (this was the source of the recent extension-test regression where the useStdio parameter was silently ignored). Throw eagerly so the mistake shows up immediately, and drop the now-redundant useStdio:false arg from every call site that also sets Connection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/ConnectionTokenTests.cs | 2 +- dotnet/test/E2E/ClientE2ETests.cs | 2 +- dotnet/test/E2E/ClientOptionsE2ETests.cs | 3 --- .../E2E/MultiClientCommandsElicitationE2ETests.cs | 2 +- dotnet/test/E2E/MultiClientE2ETests.cs | 2 +- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 12 ++++++------ dotnet/test/E2E/SessionFsE2ETests.cs | 1 - dotnet/test/E2E/SuspendE2ETests.cs | 2 +- dotnet/test/Harness/CapiProxy.cs | 4 ++++ dotnet/test/Harness/E2ETestContext.cs | 10 ++++++++++ dotnet/test/Harness/E2ETestFixture.cs | 2 +- 11 files changed, 26 insertions(+), 16 deletions(-) diff --git a/dotnet/test/ConnectionTokenTests.cs b/dotnet/test/ConnectionTokenTests.cs index 581ea655e..bf2f08fc8 100644 --- a/dotnet/test/ConnectionTokenTests.cs +++ b/dotnet/test/ConnectionTokenTests.cs @@ -22,7 +22,7 @@ public class ConnectionTokenTestFixture : IAsyncLifetime public async Task InitializeAsync() { Ctx = await E2ETestContext.CreateAsync(); - GoodClient = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: Token) }); + GoodClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: Token) }); await GoodClient.StartAsync(); Port = GoodClient.RuntimePort diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs index 5d8eec8e4..0cc344c4f 100644 --- a/dotnet/test/E2E/ClientE2ETests.cs +++ b/dotnet/test/E2E/ClientE2ETests.cs @@ -192,7 +192,7 @@ public async Task Should_Allow_ResumeSession_Called_Without_PermissionHandler() const string connectionToken = "client-e2e-resume-token"; await using var ctx = await E2ETestContext.CreateAsync(); - await using var client = ctx.CreateClient(useStdio: false, options: new CopilotClientOptions + await using var client = ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: connectionToken), }); diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index 15c07b58c..785cf9d88 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -20,7 +20,6 @@ public async Task Should_Listen_On_Configured_Tcp_Port() { var port = GetAvailableTcpPort(); await using var client = Ctx.CreateClient( - useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(port: port) }); await client.StartAsync(); @@ -227,7 +226,6 @@ public async Task ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup() await File.WriteAllTextAsync(cliPath, FakeTcpDropDuringStartupCliScript); await using var client = Ctx.CreateClient( - useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(path: cliPath), @@ -249,7 +247,6 @@ public async Task StartAsync_Cleans_Up_Tcp_Cli_Process_When_Connect_Fails() await File.WriteAllTextAsync(cliPath, FakeTcpUnavailablePortCliScript); await using var client = Ctx.CreateClient( - useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(path: cliPath, args: ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)]), diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index 98cc56e4f..d239cd433 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -22,7 +22,7 @@ public class MultiClientCommandsElicitationFixture : IAsyncLifetime public async Task InitializeAsync() { Ctx = await E2ETestContext.CreateAsync(); - Client1 = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions + Client1 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken), }, persistent: true); diff --git a/dotnet/test/E2E/MultiClientE2ETests.cs b/dotnet/test/E2E/MultiClientE2ETests.cs index 463542205..f88761dc2 100644 --- a/dotnet/test/E2E/MultiClientE2ETests.cs +++ b/dotnet/test/E2E/MultiClientE2ETests.cs @@ -24,7 +24,7 @@ public class MultiClientTestFixture : IAsyncLifetime public async Task InitializeAsync() { Ctx = await E2ETestContext.CreateAsync(); - Client1 = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions + Client1 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken), }, persistent: true); diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index 30d276b61..b13b945c4 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -24,7 +24,7 @@ public async Task Should_Continue_Pending_Permission_Request_After_Resume() var releaseOriginalPermission = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var resumedToolInvoked = false; - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); @@ -107,7 +107,7 @@ public async Task Should_Continue_Pending_External_Tool_Request_After_Resume() var originalToolStarted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var releaseOriginalTool = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); @@ -171,7 +171,7 @@ public async Task Should_Keep_Pending_External_Tool_Handleable_On_Warm_Resume_Wh var releaseOriginalTool = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var invocationCount = 0; - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); @@ -242,7 +242,7 @@ public async Task Should_Continue_Parallel_Pending_External_Tool_Requests_After_ var releaseOriginalToolA = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var releaseOriginalToolB = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); @@ -321,7 +321,7 @@ async Task BlockingToolB([Description("Value to look up")] string value) [Fact] public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() { - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); @@ -359,7 +359,7 @@ public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() [Fact] public async Task Should_Report_ContinuePendingWork_True_In_Resume_Event() { - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index fb1e57fc9..6b5a49600 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -107,7 +107,6 @@ public async Task Should_Reject_SetProvider_When_Sessions_Already_Exist() ?? throw new InvalidOperationException("Client1 is not using TCP mode; RuntimePort is null"); var client2 = Ctx.CreateClient( - useStdio: false, options: new CopilotClientOptions { LogLevel = CopilotLogLevel.Error, diff --git a/dotnet/test/E2E/SuspendE2ETests.cs b/dotnet/test/E2E/SuspendE2ETests.cs index 1f905a5f1..3dadae4e8 100644 --- a/dotnet/test/E2E/SuspendE2ETests.cs +++ b/dotnet/test/E2E/SuspendE2ETests.cs @@ -50,7 +50,7 @@ public async Task Should_Suspend_Idle_Session_Without_Throwing() public async Task Should_Allow_Resume_And_Continue_Conversation_After_Suspend() { const string sharedToken = "suspend-shared-token"; - await using var server = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: sharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: sharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); diff --git a/dotnet/test/Harness/CapiProxy.cs b/dotnet/test/Harness/CapiProxy.cs index 274055540..6e5428208 100644 --- a/dotnet/test/Harness/CapiProxy.cs +++ b/dotnet/test/Harness/CapiProxy.cs @@ -50,6 +50,10 @@ async Task StartCoreAsync() RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, + Environment = + { + ["GITHUB_ACTIONS"] = "true", + } }; _process = new Process { StartInfo = startInfo }; diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index ea28516dd..5ed93ac4c 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -3,6 +3,7 @@ *--------------------------------------------------------------------------------------------*/ using Microsoft.Extensions.Logging; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; @@ -222,6 +223,15 @@ public CopilotClient CreateClient( // Build the connection. If the caller supplied one, just ensure the runtime path is set; // otherwise default to Stdio with the bundled runtime (matches CopilotClient's own default). + // useStdio is a convenience shortcut for the no-Connection case; passing both is ambiguous. + if (useStdio is not null && options.Connection is not null) + { + throw new ArgumentException( + "Specify either useStdio or options.Connection, not both. " + + "Use options.Connection (e.g. RuntimeConnection.Stdio() / RuntimeConnection.Tcp()) to control transport when supplying a Connection.", + nameof(useStdio)); + } + var cliPath = GetCliPath(_repoRoot); switch (options.Connection) { diff --git a/dotnet/test/Harness/E2ETestFixture.cs b/dotnet/test/Harness/E2ETestFixture.cs index 5e1e090e7..07d1ef1b6 100644 --- a/dotnet/test/Harness/E2ETestFixture.cs +++ b/dotnet/test/Harness/E2ETestFixture.cs @@ -17,7 +17,7 @@ public class E2ETestFixture : IAsyncLifetime public async Task InitializeAsync() { Ctx = await E2ETestContext.CreateAsync(); - Client = Ctx.CreateClient(useStdio: false, options: new CopilotClientOptions + Client = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedTcpConnectionToken), }, persistent: true); From 8c9ede25d3f060f9dc849a74dc15528bbf439949 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 18:44:40 +0100 Subject: [PATCH 25/40] Revert accidental CapiProxy.cs change Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/Harness/CapiProxy.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dotnet/test/Harness/CapiProxy.cs b/dotnet/test/Harness/CapiProxy.cs index 6e5428208..274055540 100644 --- a/dotnet/test/Harness/CapiProxy.cs +++ b/dotnet/test/Harness/CapiProxy.cs @@ -50,10 +50,6 @@ async Task StartCoreAsync() RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, - Environment = - { - ["GITHUB_ACTIONS"] = "true", - } }; _process = new Process { StartInfo = startInfo }; From 6633928cee707101ae226f7e4ab3d7ccfdc8a16c Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 18:52:23 +0100 Subject: [PATCH 26/40] Test fix --- dotnet/test/E2E/SessionFsE2ETests.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index 6b5a49600..aa124ea95 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -455,13 +455,16 @@ public async Task Should_Persist_Plan_Md_Via_SessionFs() private CopilotClient CreateSessionFsClient(string providerRoot, bool useStdio = true, string? tcpConnectionToken = null) { + RuntimeConnection connection = useStdio + ? RuntimeConnection.Stdio() + : RuntimeConnection.Tcp(connectionToken: tcpConnectionToken); + Directory.CreateDirectory(providerRoot); return Ctx.CreateClient( - useStdio: useStdio, options: new CopilotClientOptions { SessionFs = SessionFsConfig, - Connection = RuntimeConnection.Tcp(connectionToken: tcpConnectionToken), + Connection = connection, }); } From 32567bf8d73d7ed15ef02121694136ab00cb1e4f Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:15:02 +0100 Subject: [PATCH 27/40] Update C# doc snippets for renamed APIs Replace CliPath/CliArgs/CliUrl/UseStdio with RuntimeConnection.Stdio/Tcp/Uri, CopilotHome with BaseDirectory, McpStdioServerConfig.Cwd with WorkingDirectory, GithubToken with GitHubToken, and add explicit type args to session.On() / client.OnLifecycle() calls in C# code blocks across the docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/auth/authenticate.md | 4 ++-- docs/features/custom-agents.md | 4 ++-- docs/features/streaming-events.md | 4 ++-- docs/getting-started.md | 17 ++++++++--------- docs/setup/backend-services.md | 6 ++---- docs/setup/github-oauth.md | 4 ++-- docs/setup/local-cli.md | 2 +- docs/troubleshooting/debugging.md | 2 +- docs/troubleshooting/mcp-debugging.md | 8 ++++---- 9 files changed, 24 insertions(+), 27 deletions(-) diff --git a/docs/auth/authenticate.md b/docs/auth/authenticate.md index 740e5f3c1..32a09ffe7 100644 --- a/docs/auth/authenticate.md +++ b/docs/auth/authenticate.md @@ -184,7 +184,7 @@ using GitHub.Copilot.SDK; var userAccessToken = "token"; await using var client = new CopilotClient(new CopilotClientOptions { - GithubToken = userAccessToken, + GitHubToken = userAccessToken, UseLoggedInUser = false, }); ``` @@ -195,7 +195,7 @@ using GitHub.Copilot.SDK; await using var client = new CopilotClient(new CopilotClientOptions { - GithubToken = userAccessToken, // Token from OAuth flow + GitHubToken = userAccessToken, // Token from OAuth flow UseLoggedInUser = false, // Don't use stored CLI credentials }); ``` diff --git a/docs/features/custom-agents.md b/docs/features/custom-agents.md index 71fd9b4b1..c49bc9ef7 100644 --- a/docs/features/custom-agents.md +++ b/docs/features/custom-agents.md @@ -591,7 +591,7 @@ public static class SubAgentEventsExample { public static async Task Example(CopilotSession session) { - using var subscription = session.On(evt => + using var subscription = session.On(evt => { switch (evt) { @@ -622,7 +622,7 @@ public static class SubAgentEventsExample ```csharp -using var subscription = session.On(evt => +using var subscription = session.On(evt => { switch (evt) { diff --git a/docs/features/streaming-events.md b/docs/features/streaming-events.md index a12440ee5..c0944c05c 100644 --- a/docs/features/streaming-events.md +++ b/docs/features/streaming-events.md @@ -167,7 +167,7 @@ public static class StreamingEventsExample { public static async Task Example(CopilotSession session) { - session.On(evt => + session.On(evt => { if (evt is AssistantMessageDeltaEvent delta) { @@ -180,7 +180,7 @@ public static class StreamingEventsExample ```csharp -session.On(evt => +session.On(evt => { if (evt is AssistantMessageDeltaEvent delta) { diff --git a/docs/getting-started.md b/docs/getting-started.md index 0836f2567..9b68fd5f4 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -568,7 +568,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig }); // Listen for response chunks -session.On(ev => +session.On(ev => { if (ev is AssistantMessageDeltaEvent deltaEvent) { @@ -807,10 +807,10 @@ public static class EventSubscriptionExample public static void Example(CopilotSession session) { // Subscribe to all events - var unsubscribe = session.On(ev => Console.WriteLine($"Event: {ev.Type}")); + var unsubscribe = session.On(ev => Console.WriteLine($"Event: {ev.Type}")); // Filter by event type using pattern matching - session.On(ev => + session.On(ev => { switch (ev) { @@ -832,10 +832,10 @@ public static class EventSubscriptionExample ```csharp // Subscribe to all events -var unsubscribe = session.On(ev => Console.WriteLine($"Event: {ev.Type}")); +var unsubscribe = session.On(ev => Console.WriteLine($"Event: {ev.Type}")); // Filter by event type using pattern matching -session.On(ev => +session.On(ev => { switch (ev) { @@ -1190,7 +1190,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig Tools = [getWeather], }); -session.On(ev => +session.On(ev => { if (ev is AssistantMessageDeltaEvent deltaEvent) { @@ -1676,7 +1676,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig }); // Listen for response chunks -session.On(ev => +session.On(ev => { if (ev is AssistantMessageDeltaEvent deltaEvent) { @@ -2071,8 +2071,7 @@ using GitHub.Copilot.SDK; using var client = new CopilotClient(new CopilotClientOptions { - CliUrl = "localhost:4321", - UseStdio = false +Connection = RuntimeConnection.Uri("localhost:4321"), }); // Use the client normally diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md index 655453667..9901d73c8 100644 --- a/docs/setup/backend-services.md +++ b/docs/setup/backend-services.md @@ -222,8 +222,7 @@ var message = "Hello"; var client = new CopilotClient(new CopilotClientOptions { - CliUrl = "localhost:4321", - UseStdio = false, +Connection = RuntimeConnection.Uri("localhost:4321"), }); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -240,8 +239,7 @@ var response = await session.SendAndWaitAsync( ```csharp var client = new CopilotClient(new CopilotClientOptions { - CliUrl = "localhost:4321", - UseStdio = false, +Connection = RuntimeConnection.Uri("localhost:4321"), }); await using var session = await client.CreateSessionAsync(new SessionConfig diff --git a/docs/setup/github-oauth.md b/docs/setup/github-oauth.md index 31a3b9001..8381e405c 100644 --- a/docs/setup/github-oauth.md +++ b/docs/setup/github-oauth.md @@ -235,7 +235,7 @@ using GitHub.Copilot.SDK; CopilotClient CreateClientForUser(string userToken) => new CopilotClient(new CopilotClientOptions { - GithubToken = userToken, + GitHubToken = userToken, UseLoggedInUser = false, }); @@ -257,7 +257,7 @@ var response = await session.SendAndWaitAsync( CopilotClient CreateClientForUser(string userToken) => new CopilotClient(new CopilotClientOptions { - GithubToken = userToken, + GitHubToken = userToken, UseLoggedInUser = false, }); diff --git a/docs/setup/local-cli.md b/docs/setup/local-cli.md index 28bef7b20..95c6b230a 100644 --- a/docs/setup/local-cli.md +++ b/docs/setup/local-cli.md @@ -139,7 +139,7 @@ if response != nil { ```csharp var client = new CopilotClient(new CopilotClientOptions { - CliPath = "/usr/local/bin/copilot", + Connection = RuntimeConnection.Stdio(path: "/usr/local/bin/copilot"), }); await using var session = await client.CreateSessionAsync( diff --git a/docs/troubleshooting/debugging.md b/docs/troubleshooting/debugging.md index 7092899fd..cd78bd2e7 100644 --- a/docs/troubleshooting/debugging.md +++ b/docs/troubleshooting/debugging.md @@ -164,7 +164,7 @@ func main() { ```csharp var client = new CopilotClient(new CopilotClientOptions { - CliArgs = new[] { "--log-dir", "/path/to/logs" } + Connection = RuntimeConnection.Stdio(args: new[] { "--log-dir", "/path/to/logs" }) }); ``` diff --git a/docs/troubleshooting/mcp-debugging.md b/docs/troubleshooting/mcp-debugging.md index eb98eb1bd..34cab28c1 100644 --- a/docs/troubleshooting/mcp-debugging.md +++ b/docs/troubleshooting/mcp-debugging.md @@ -248,14 +248,14 @@ public static class McpDotnetConfigExample { Command = @"C:\Tools\MyServer\MyServer.exe", Args = new List(), - Cwd = @"C:\Tools\MyServer", + WorkingDirectory = @"C:\Tools\MyServer", Tools = new List { "*" }, }, ["my-dotnet-tool"] = new McpStdioServerConfig { Command = "dotnet", Args = new List { @"C:\Tools\MyTool\MyTool.dll" }, - Cwd = @"C:\Tools\MyTool", + WorkingDirectory = @"C:\Tools\MyTool", Tools = new List { "*" }, } }; @@ -269,7 +269,7 @@ public static class McpDotnetConfigExample { Command = @"C:\Tools\MyServer\MyServer.exe", // Full path with .exe Args = new List(), - Cwd = @"C:\Tools\MyServer", // Set working directory + WorkingDirectory = @"C:\Tools\MyServer", // Set working directory Tools = new List { "*" }, } @@ -278,7 +278,7 @@ public static class McpDotnetConfigExample { Command = "dotnet", Args = new List { @"C:\Tools\MyTool\MyTool.dll" }, - Cwd = @"C:\Tools\MyTool", + WorkingDirectory = @"C:\Tools\MyTool", Tools = new List { "*" }, } ``` From 99d0fcd68acc6628c2cfe4a1a3cc5d590b713ef2 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:20:58 +0100 Subject: [PATCH 28/40] Update C# test scenarios for renamed APIs Replace CliPath/CliUrl with RuntimeConnection.Stdio/Uri and add explicit type args to session.On() across all C# scenario programs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/scenarios/auth/byok-anthropic/csharp/Program.cs | 2 +- test/scenarios/auth/byok-azure/csharp/Program.cs | 2 +- test/scenarios/auth/byok-ollama/csharp/Program.cs | 2 +- test/scenarios/auth/byok-openai/csharp/Program.cs | 2 +- test/scenarios/auth/gh-app/csharp/Program.cs | 2 +- .../bundling/app-backend-to-server/csharp/Program.cs | 2 +- test/scenarios/bundling/app-direct-server/csharp/Program.cs | 2 +- test/scenarios/bundling/container-proxy/csharp/Program.cs | 2 +- test/scenarios/bundling/fully-bundled/csharp/Program.cs | 2 +- test/scenarios/callbacks/hooks/csharp/Program.cs | 2 +- test/scenarios/callbacks/permissions/csharp/Program.cs | 2 +- test/scenarios/callbacks/user-input/csharp/Program.cs | 2 +- test/scenarios/modes/default/csharp/Program.cs | 2 +- test/scenarios/modes/minimal/csharp/Program.cs | 2 +- test/scenarios/prompts/attachments/csharp/Program.cs | 2 +- test/scenarios/prompts/reasoning-effort/csharp/Program.cs | 2 +- test/scenarios/prompts/system-message/csharp/Program.cs | 2 +- test/scenarios/sessions/concurrent-sessions/csharp/Program.cs | 2 +- test/scenarios/sessions/infinite-sessions/csharp/Program.cs | 2 +- test/scenarios/sessions/session-resume/csharp/Program.cs | 2 +- test/scenarios/sessions/streaming/csharp/Program.cs | 4 ++-- test/scenarios/tools/custom-agents/csharp/Program.cs | 2 +- test/scenarios/tools/mcp-servers/csharp/Program.cs | 2 +- test/scenarios/tools/no-tools/csharp/Program.cs | 2 +- test/scenarios/tools/skills/csharp/Program.cs | 2 +- test/scenarios/tools/tool-filtering/csharp/Program.cs | 2 +- test/scenarios/tools/tool-overrides/csharp/Program.cs | 2 +- test/scenarios/tools/virtual-filesystem/csharp/Program.cs | 2 +- test/scenarios/transport/reconnect/csharp/Program.cs | 2 +- test/scenarios/transport/stdio/csharp/Program.cs | 2 +- test/scenarios/transport/tcp/csharp/Program.cs | 2 +- 31 files changed, 32 insertions(+), 32 deletions(-) diff --git a/test/scenarios/auth/byok-anthropic/csharp/Program.cs b/test/scenarios/auth/byok-anthropic/csharp/Program.cs index 6bb9dd231..7e24c0fec 100644 --- a/test/scenarios/auth/byok-anthropic/csharp/Program.cs +++ b/test/scenarios/auth/byok-anthropic/csharp/Program.cs @@ -12,7 +12,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/byok-azure/csharp/Program.cs b/test/scenarios/auth/byok-azure/csharp/Program.cs index e6b2789a1..fc8589856 100644 --- a/test/scenarios/auth/byok-azure/csharp/Program.cs +++ b/test/scenarios/auth/byok-azure/csharp/Program.cs @@ -13,7 +13,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/byok-ollama/csharp/Program.cs b/test/scenarios/auth/byok-ollama/csharp/Program.cs index 585157b66..f0b98e3c7 100644 --- a/test/scenarios/auth/byok-ollama/csharp/Program.cs +++ b/test/scenarios/auth/byok-ollama/csharp/Program.cs @@ -8,7 +8,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/byok-openai/csharp/Program.cs b/test/scenarios/auth/byok-openai/csharp/Program.cs index 5d549bd5c..187c3c058 100644 --- a/test/scenarios/auth/byok-openai/csharp/Program.cs +++ b/test/scenarios/auth/byok-openai/csharp/Program.cs @@ -12,7 +12,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/gh-app/csharp/Program.cs b/test/scenarios/auth/gh-app/csharp/Program.cs index 1f2e27ccf..f40349365 100644 --- a/test/scenarios/auth/gh-app/csharp/Program.cs +++ b/test/scenarios/auth/gh-app/csharp/Program.cs @@ -60,7 +60,7 @@ // Step 4: Use the token with Copilot using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = accessToken, }); diff --git a/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs b/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs index df3a335b0..317ce4e38 100644 --- a/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs +++ b/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs @@ -21,7 +21,7 @@ return; } - using var client = new CopilotClient(new CopilotClientOptions { CliUrl = cliUrl }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/bundling/app-direct-server/csharp/Program.cs b/test/scenarios/bundling/app-direct-server/csharp/Program.cs index 6dd14e9db..bbf42b940 100644 --- a/test/scenarios/bundling/app-direct-server/csharp/Program.cs +++ b/test/scenarios/bundling/app-direct-server/csharp/Program.cs @@ -2,7 +2,7 @@ var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; -using var client = new CopilotClient(new CopilotClientOptions { CliUrl = cliUrl }); +using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/bundling/container-proxy/csharp/Program.cs b/test/scenarios/bundling/container-proxy/csharp/Program.cs index 6dd14e9db..bbf42b940 100644 --- a/test/scenarios/bundling/container-proxy/csharp/Program.cs +++ b/test/scenarios/bundling/container-proxy/csharp/Program.cs @@ -2,7 +2,7 @@ var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; -using var client = new CopilotClient(new CopilotClientOptions { CliUrl = cliUrl }); +using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/bundling/fully-bundled/csharp/Program.cs b/test/scenarios/bundling/fully-bundled/csharp/Program.cs index cb67c903c..8a93141f5 100644 --- a/test/scenarios/bundling/fully-bundled/csharp/Program.cs +++ b/test/scenarios/bundling/fully-bundled/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/callbacks/hooks/csharp/Program.cs b/test/scenarios/callbacks/hooks/csharp/Program.cs index 63c15128f..7ea902f52 100644 --- a/test/scenarios/callbacks/hooks/csharp/Program.cs +++ b/test/scenarios/callbacks/hooks/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/callbacks/permissions/csharp/Program.cs b/test/scenarios/callbacks/permissions/csharp/Program.cs index 889eeaff1..2c1a650be 100644 --- a/test/scenarios/callbacks/permissions/csharp/Program.cs +++ b/test/scenarios/callbacks/permissions/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/callbacks/user-input/csharp/Program.cs b/test/scenarios/callbacks/user-input/csharp/Program.cs index 6ad0454d7..a73b65155 100644 --- a/test/scenarios/callbacks/user-input/csharp/Program.cs +++ b/test/scenarios/callbacks/user-input/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/modes/default/csharp/Program.cs b/test/scenarios/modes/default/csharp/Program.cs index 243fcb922..85f44ad20 100644 --- a/test/scenarios/modes/default/csharp/Program.cs +++ b/test/scenarios/modes/default/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/modes/minimal/csharp/Program.cs b/test/scenarios/modes/minimal/csharp/Program.cs index 94cbc2034..652bfcaa4 100644 --- a/test/scenarios/modes/minimal/csharp/Program.cs +++ b/test/scenarios/modes/minimal/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/prompts/attachments/csharp/Program.cs b/test/scenarios/prompts/attachments/csharp/Program.cs index 272c89aab..2868f9740 100644 --- a/test/scenarios/prompts/attachments/csharp/Program.cs +++ b/test/scenarios/prompts/attachments/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/prompts/reasoning-effort/csharp/Program.cs b/test/scenarios/prompts/reasoning-effort/csharp/Program.cs index 719650880..bb01d0c81 100644 --- a/test/scenarios/prompts/reasoning-effort/csharp/Program.cs +++ b/test/scenarios/prompts/reasoning-effort/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/prompts/system-message/csharp/Program.cs b/test/scenarios/prompts/system-message/csharp/Program.cs index 5f22cb029..c0e92673c 100644 --- a/test/scenarios/prompts/system-message/csharp/Program.cs +++ b/test/scenarios/prompts/system-message/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs b/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs index 142bcb268..bf4b33fba 100644 --- a/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs +++ b/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs @@ -5,7 +5,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/infinite-sessions/csharp/Program.cs b/test/scenarios/sessions/infinite-sessions/csharp/Program.cs index fe281292d..82c0f3001 100644 --- a/test/scenarios/sessions/infinite-sessions/csharp/Program.cs +++ b/test/scenarios/sessions/infinite-sessions/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/session-resume/csharp/Program.cs b/test/scenarios/sessions/session-resume/csharp/Program.cs index 73979669d..31f233313 100644 --- a/test/scenarios/sessions/session-resume/csharp/Program.cs +++ b/test/scenarios/sessions/session-resume/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/streaming/csharp/Program.cs b/test/scenarios/sessions/streaming/csharp/Program.cs index 01683df76..5dcc3182b 100644 --- a/test/scenarios/sessions/streaming/csharp/Program.cs +++ b/test/scenarios/sessions/streaming/csharp/Program.cs @@ -8,7 +8,7 @@ var cliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"); if (!string.IsNullOrEmpty(cliPath)) { - options.CliPath = cliPath; + options.Connection = RuntimeConnection.Stdio(path: cliPath); } using var client = new CopilotClient(options); @@ -24,7 +24,7 @@ }); var chunkCount = 0; - using var subscription = session.On(evt => + using var subscription = session.On(evt => { if (evt is AssistantMessageDeltaEvent) { diff --git a/test/scenarios/tools/custom-agents/csharp/Program.cs b/test/scenarios/tools/custom-agents/csharp/Program.cs index d3c068ade..90721c2a2 100644 --- a/test/scenarios/tools/custom-agents/csharp/Program.cs +++ b/test/scenarios/tools/custom-agents/csharp/Program.cs @@ -5,7 +5,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = cliPath, + Connection = RuntimeConnection.Stdio(path: cliPath), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/mcp-servers/csharp/Program.cs b/test/scenarios/tools/mcp-servers/csharp/Program.cs index e3c1ed428..739ca058b 100644 --- a/test/scenarios/tools/mcp-servers/csharp/Program.cs +++ b/test/scenarios/tools/mcp-servers/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/no-tools/csharp/Program.cs b/test/scenarios/tools/no-tools/csharp/Program.cs index c3de1de53..619b05266 100644 --- a/test/scenarios/tools/no-tools/csharp/Program.cs +++ b/test/scenarios/tools/no-tools/csharp/Program.cs @@ -9,7 +9,7 @@ You can only respond with text based on your training data. using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/skills/csharp/Program.cs b/test/scenarios/tools/skills/csharp/Program.cs index d0394a396..4fb229df9 100644 --- a/test/scenarios/tools/skills/csharp/Program.cs +++ b/test/scenarios/tools/skills/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/tool-filtering/csharp/Program.cs b/test/scenarios/tools/tool-filtering/csharp/Program.cs index f21482b1b..30bc29881 100644 --- a/test/scenarios/tools/tool-filtering/csharp/Program.cs +++ b/test/scenarios/tools/tool-filtering/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/tool-overrides/csharp/Program.cs b/test/scenarios/tools/tool-overrides/csharp/Program.cs index be8c07ec8..9224b3aee 100644 --- a/test/scenarios/tools/tool-overrides/csharp/Program.cs +++ b/test/scenarios/tools/tool-overrides/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/virtual-filesystem/csharp/Program.cs b/test/scenarios/tools/virtual-filesystem/csharp/Program.cs index d67a3738c..8e2566ee5 100644 --- a/test/scenarios/tools/virtual-filesystem/csharp/Program.cs +++ b/test/scenarios/tools/virtual-filesystem/csharp/Program.cs @@ -7,7 +7,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/transport/reconnect/csharp/Program.cs b/test/scenarios/transport/reconnect/csharp/Program.cs index 80dc482da..b79246eda 100644 --- a/test/scenarios/transport/reconnect/csharp/Program.cs +++ b/test/scenarios/transport/reconnect/csharp/Program.cs @@ -2,7 +2,7 @@ var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; -using var client = new CopilotClient(new CopilotClientOptions { CliUrl = cliUrl }); +using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/transport/stdio/csharp/Program.cs b/test/scenarios/transport/stdio/csharp/Program.cs index cb67c903c..8a93141f5 100644 --- a/test/scenarios/transport/stdio/csharp/Program.cs +++ b/test/scenarios/transport/stdio/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"), + Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/transport/tcp/csharp/Program.cs b/test/scenarios/transport/tcp/csharp/Program.cs index 051c877d2..6e85aae3d 100644 --- a/test/scenarios/transport/tcp/csharp/Program.cs +++ b/test/scenarios/transport/tcp/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - CliUrl = cliUrl, + Connection = RuntimeConnection.Uri(cliUrl), }); await client.StartAsync(); From 4b72cf584908489fe1d1b5028d06f7ead37e8c85 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:40:47 +0100 Subject: [PATCH 29/40] Drop .SDK from C# namespaces GitHub.Copilot.SDK -> GitHub.Copilot (and all sub-namespaces in step). The package name and csproj/.targets/.props filenames still include .SDK, so RootNamespace is set explicitly on both csproj files to override the default derived from the assembly name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/auth/authenticate.md | 6 +- docs/auth/byok.md | 4 +- docs/features/custom-agents.md | 4 +- docs/features/hooks.md | 4 +- docs/features/image-input.md | 6 +- docs/features/mcp.md | 2 +- docs/features/session-persistence.md | 4 +- docs/features/skills.md | 4 +- docs/features/steering-and-queueing.md | 4 +- docs/features/streaming-events.md | 2 +- docs/getting-started.md | 14 +- docs/hooks/error-handling.md | 4 +- docs/hooks/hooks-overview.md | 2 +- docs/hooks/post-tool-use.md | 4 +- docs/hooks/pre-tool-use.md | 4 +- docs/hooks/session-lifecycle.md | 2 +- docs/hooks/user-prompt-submitted.md | 4 +- .../integrations/microsoft-agent-framework.md | 12 +- docs/setup/backend-services.md | 2 +- docs/setup/choosing-a-setup-path.md | 2 +- docs/setup/github-oauth.md | 2 +- docs/troubleshooting/debugging.md | 2 +- docs/troubleshooting/mcp-debugging.md | 4 +- dotnet/README.md | 6 +- dotnet/samples/Chat.cs | 2 +- dotnet/samples/ManualToolResume.cs | 4 +- dotnet/src/ActionDisposable.cs | 2 +- dotnet/src/Client.cs | 6 +- dotnet/src/CopilotTool.cs | 2 +- dotnet/src/Generated/Rpc.cs | 616 +++++++++--------- dotnet/src/Generated/SessionEvents.cs | 114 ++-- dotnet/src/GitHub.Copilot.SDK.csproj | 1 + dotnet/src/JsonRpc.cs | 2 +- dotnet/src/LoggingHelpers.cs | 2 +- dotnet/src/MillisecondsTimeSpanConverter.cs | 2 +- dotnet/src/PermissionHandlers.cs | 2 +- dotnet/src/SdkProtocolVersion.cs | 2 +- dotnet/src/Session.cs | 4 +- dotnet/src/SessionFsProvider.cs | 4 +- dotnet/src/Telemetry.cs | 2 +- dotnet/src/Types.cs | 4 +- ...UnixMillisecondsDateTimeOffsetConverter.cs | 2 +- dotnet/test/ConnectionTokenTests.cs | 4 +- dotnet/test/E2E/AbortE2ETests.cs | 2 +- dotnet/test/E2E/AskUserE2ETests.cs | 4 +- dotnet/test/E2E/BuiltinToolsE2ETests.cs | 2 +- dotnet/test/E2E/ClientE2ETests.cs | 4 +- dotnet/test/E2E/ClientLifecycleE2ETests.cs | 4 +- dotnet/test/E2E/ClientOptionsE2ETests.cs | 2 +- .../E2E/ClientSessionManagementE2ETests.cs | 2 +- dotnet/test/E2E/CommandsE2ETests.cs | 2 +- dotnet/test/E2E/CompactionE2ETests.cs | 4 +- dotnet/test/E2E/ElicitationE2ETests.cs | 4 +- dotnet/test/E2E/ErrorResilienceE2ETests.cs | 2 +- dotnet/test/E2E/EventFidelityE2ETests.cs | 4 +- .../E2E/HookLifecycleAndOutputE2ETests.cs | 2 +- dotnet/test/E2E/HooksE2ETests.cs | 4 +- .../E2E/InMemorySessionFsSqliteHandler.cs | 6 +- dotnet/test/E2E/ModeHandlersE2ETests.cs | 4 +- .../MultiClientCommandsElicitationE2ETests.cs | 4 +- dotnet/test/E2E/MultiClientE2ETests.cs | 4 +- dotnet/test/E2E/MultiTurnE2ETests.cs | 2 +- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 6 +- dotnet/test/E2E/PerSessionAuthE2ETests.cs | 4 +- dotnet/test/E2E/PermissionE2ETests.cs | 4 +- .../E2E/RpcAdditionalEdgeCasesE2ETests.cs | 6 +- dotnet/test/E2E/RpcAgentE2ETests.cs | 6 +- .../test/E2E/RpcEventSideEffectsE2ETests.cs | 6 +- .../test/E2E/RpcExtensionsLoadedE2ETests.cs | 8 +- dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs | 6 +- dotnet/test/E2E/RpcMcpConfigE2ETests.cs | 4 +- dotnet/test/E2E/RpcServerE2ETests.cs | 4 +- dotnet/test/E2E/RpcSessionStateE2ETests.cs | 6 +- dotnet/test/E2E/RpcShellAndFleetE2ETests.cs | 4 +- dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs | 6 +- .../test/E2E/RpcTasksAndHandlersE2ETests.cs | 14 +- dotnet/test/E2E/SessionConfigE2ETests.cs | 6 +- dotnet/test/E2E/SessionE2ETests.cs | 6 +- dotnet/test/E2E/SessionFsE2ETests.cs | 6 +- dotnet/test/E2E/SessionFsSqliteE2ETests.cs | 6 +- dotnet/test/E2E/SessionLifecycleE2ETests.cs | 4 +- .../E2E/SessionMcpAndAgentConfigE2ETests.cs | 6 +- dotnet/test/E2E/SkillsE2ETests.cs | 2 +- dotnet/test/E2E/StreamingFidelityE2ETests.cs | 2 +- dotnet/test/E2E/SubagentHooksE2ETests.cs | 4 +- dotnet/test/E2E/SuspendE2ETests.cs | 2 +- .../E2E/SystemMessageTransformE2ETests.cs | 4 +- dotnet/test/E2E/TelemetryExportE2ETests.cs | 4 +- dotnet/test/E2E/ToolResultsE2ETests.cs | 4 +- dotnet/test/E2E/ToolsE2ETests.cs | 4 +- dotnet/test/GitHub.Copilot.SDK.Test.csproj | 1 + dotnet/test/Harness/CapiProxy.cs | 2 +- dotnet/test/Harness/E2ETestBase.cs | 4 +- dotnet/test/Harness/E2ETestContext.cs | 2 +- dotnet/test/Harness/E2ETestFixture.cs | 4 +- dotnet/test/Harness/TestHelper.cs | 2 +- .../test/Unit/ClientSessionLifetimeTests.cs | 2 +- dotnet/test/Unit/CloneTests.cs | 2 +- dotnet/test/Unit/CopilotToolTests.cs | 2 +- dotnet/test/Unit/ForwardCompatibilityTests.cs | 8 +- dotnet/test/Unit/JsonRpcTests.cs | 6 +- dotnet/test/Unit/MSBuildTargetsTests.cs | 2 +- .../Unit/PermissionRequestResultKindTests.cs | 2 +- dotnet/test/Unit/PublicDtoTests.cs | 4 +- dotnet/test/Unit/SerializationTests.cs | 4 +- .../Unit/SessionEventSerializationTests.cs | 2 +- dotnet/test/Unit/TelemetryTests.cs | 4 +- scripts/codegen/csharp.ts | 10 +- .../auth/byok-anthropic/csharp/Program.cs | 2 +- .../auth/byok-azure/csharp/Program.cs | 2 +- .../auth/byok-ollama/csharp/Program.cs | 2 +- .../auth/byok-openai/csharp/Program.cs | 2 +- test/scenarios/auth/gh-app/csharp/Program.cs | 2 +- .../app-backend-to-server/csharp/Program.cs | 2 +- .../app-direct-server/csharp/Program.cs | 2 +- .../container-proxy/csharp/Program.cs | 2 +- .../bundling/fully-bundled/csharp/Program.cs | 2 +- .../callbacks/hooks/csharp/Program.cs | 2 +- .../callbacks/permissions/csharp/Program.cs | 2 +- .../callbacks/user-input/csharp/Program.cs | 2 +- .../scenarios/modes/default/csharp/Program.cs | 2 +- .../scenarios/modes/minimal/csharp/Program.cs | 2 +- .../prompts/attachments/csharp/Program.cs | 2 +- .../reasoning-effort/csharp/Program.cs | 2 +- .../prompts/system-message/csharp/Program.cs | 2 +- .../concurrent-sessions/csharp/Program.cs | 2 +- .../infinite-sessions/csharp/Program.cs | 2 +- .../sessions/session-resume/csharp/Program.cs | 2 +- .../sessions/streaming/csharp/Program.cs | 2 +- .../tools/custom-agents/csharp/Program.cs | 2 +- .../tools/mcp-servers/csharp/Program.cs | 2 +- .../tools/no-tools/csharp/Program.cs | 2 +- test/scenarios/tools/skills/csharp/Program.cs | 2 +- .../tools/tool-filtering/csharp/Program.cs | 2 +- .../tools/tool-overrides/csharp/Program.cs | 2 +- .../virtual-filesystem/csharp/Program.cs | 2 +- .../transport/reconnect/csharp/Program.cs | 2 +- .../transport/stdio/csharp/Program.cs | 2 +- .../scenarios/transport/tcp/csharp/Program.cs | 2 +- 139 files changed, 607 insertions(+), 605 deletions(-) diff --git a/docs/auth/authenticate.md b/docs/auth/authenticate.md index 32a09ffe7..d2fb11603 100644 --- a/docs/auth/authenticate.md +++ b/docs/auth/authenticate.md @@ -77,7 +77,7 @@ client := copilot.NewClient(nil) .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; // Default: uses logged-in user credentials await using var client = new CopilotClient(); @@ -179,7 +179,7 @@ client := copilot.NewClient(&copilot.ClientOptions{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; var userAccessToken = "token"; await using var client = new CopilotClient(new CopilotClientOptions @@ -191,7 +191,7 @@ await using var client = new CopilotClient(new CopilotClientOptions ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(new CopilotClientOptions { diff --git a/docs/auth/byok.md b/docs/auth/byok.md index 95b4a1c74..cb2f8cb90 100644 --- a/docs/auth/byok.md +++ b/docs/auth/byok.md @@ -142,7 +142,7 @@ func main() { .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -424,7 +424,7 @@ func main() { .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; var client = new CopilotClient(new CopilotClientOptions { diff --git a/docs/features/custom-agents.md b/docs/features/custom-agents.md index c49bc9ef7..3d93f7589 100644 --- a/docs/features/custom-agents.md +++ b/docs/features/custom-agents.md @@ -173,7 +173,7 @@ session, _ := client.CreateSession(ctx, &copilot.SessionConfig{ .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -585,7 +585,7 @@ _, err := session.SendAndWait(ctx, copilot.MessageOptions{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class SubAgentEventsExample { diff --git a/docs/features/hooks.md b/docs/features/hooks.md index db9ad72ec..c88c6e605 100644 --- a/docs/features/hooks.md +++ b/docs/features/hooks.md @@ -146,7 +146,7 @@ session, err := client.CreateSession(ctx, &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class HooksExample { @@ -348,7 +348,7 @@ session, _ := client.CreateSession(ctx, &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class PermissionControlExample { diff --git a/docs/features/image-input.md b/docs/features/image-input.md index 286414c91..4aa564558 100644 --- a/docs/features/image-input.md +++ b/docs/features/image-input.md @@ -161,7 +161,7 @@ session.Send(ctx, copilot.MessageOptions{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class ImageInputExample { @@ -193,7 +193,7 @@ public static class ImageInputExample ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -376,7 +376,7 @@ session.Send(ctx, copilot.MessageOptions{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class BlobAttachmentExample { diff --git a/docs/features/mcp.md b/docs/features/mcp.md index f6c5a7d7e..6f715bd2e 100644 --- a/docs/features/mcp.md +++ b/docs/features/mcp.md @@ -136,7 +136,7 @@ func main() { ### .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig diff --git a/docs/features/session-persistence.md b/docs/features/session-persistence.md index 374497711..5a1987227 100644 --- a/docs/features/session-persistence.md +++ b/docs/features/session-persistence.md @@ -109,7 +109,7 @@ session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Analyze my codebase"}) ### C# (.NET) ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; var client = new CopilotClient(); @@ -201,7 +201,7 @@ session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "What did we discuss ear ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class ResumeSessionExample { diff --git a/docs/features/skills.md b/docs/features/skills.md index 6db0d60f3..516c11762 100644 --- a/docs/features/skills.md +++ b/docs/features/skills.md @@ -116,7 +116,7 @@ func main() { .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -244,7 +244,7 @@ session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class SkillsExample { diff --git a/docs/features/steering-and-queueing.md b/docs/features/steering-and-queueing.md index 7858a7d3f..ce4f4fba2 100644 --- a/docs/features/steering-and-queueing.md +++ b/docs/features/steering-and-queueing.md @@ -152,7 +152,7 @@ func main() { .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -361,7 +361,7 @@ session.Send(ctx, copilot.MessageOptions{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class QueueingExample { diff --git a/docs/features/streaming-events.md b/docs/features/streaming-events.md index c0944c05c..6bc560a48 100644 --- a/docs/features/streaming-events.md +++ b/docs/features/streaming-events.md @@ -161,7 +161,7 @@ session.On(func(event copilot.SessionEvent) { ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class StreamingEventsExample { diff --git a/docs/getting-started.md b/docs/getting-started.md index 9b68fd5f4..9e6e5f357 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -109,7 +109,7 @@ dotnet new console -n CopilotDemo && cd CopilotDemo Then add the SDK: ```bash -dotnet add package GitHub.Copilot.SDK +dotnet add package GitHub.Copilot ``` @@ -299,7 +299,7 @@ cargo run Create a new console project and add this to `Program.cs`: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -557,7 +557,7 @@ async fn main() -> Result<(), Box> { Update `Program.cs`: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -800,7 +800,7 @@ tokio::spawn(async move { ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class EventSubscriptionExample { @@ -1159,7 +1159,7 @@ async fn main() -> Result<(), Box> { Update `Program.cs`: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.AI; using System.ComponentModel; @@ -1647,7 +1647,7 @@ cargo run Create a new console project and update `Program.cs`: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.AI; using System.ComponentModel; @@ -2067,7 +2067,7 @@ let session = client .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/docs/hooks/error-handling.md b/docs/hooks/error-handling.md index 803032432..f36573f31 100644 --- a/docs/hooks/error-handling.md +++ b/docs/hooks/error-handling.md @@ -84,7 +84,7 @@ type ErrorOccurredHandler func( ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public delegate Task ErrorOccurredHandler( ErrorOccurredHookInput input, @@ -226,7 +226,7 @@ session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class ErrorHandlingExample { diff --git a/docs/hooks/hooks-overview.md b/docs/hooks/hooks-overview.md index a5f5981f4..460813c26 100644 --- a/docs/hooks/hooks-overview.md +++ b/docs/hooks/hooks-overview.md @@ -124,7 +124,7 @@ func main() { .NET ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; var client = new CopilotClient(); diff --git a/docs/hooks/post-tool-use.md b/docs/hooks/post-tool-use.md index 47262415f..f3c6f6799 100644 --- a/docs/hooks/post-tool-use.md +++ b/docs/hooks/post-tool-use.md @@ -84,7 +84,7 @@ type PostToolUseHandler func( ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public delegate Task PostToolUseHandler( PostToolUseHookInput input, @@ -219,7 +219,7 @@ session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class PostToolUseExample { diff --git a/docs/hooks/pre-tool-use.md b/docs/hooks/pre-tool-use.md index e3509dd0a..6e568d8a2 100644 --- a/docs/hooks/pre-tool-use.md +++ b/docs/hooks/pre-tool-use.md @@ -84,7 +84,7 @@ type PreToolUseHandler func( ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public delegate Task PreToolUseHandler( PreToolUseHookInput input, @@ -228,7 +228,7 @@ session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class PreToolUseExample { diff --git a/docs/hooks/session-lifecycle.md b/docs/hooks/session-lifecycle.md index b4ff502d5..83b75a32f 100644 --- a/docs/hooks/session-lifecycle.md +++ b/docs/hooks/session-lifecycle.md @@ -88,7 +88,7 @@ type SessionStartHandler func( ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public delegate Task SessionStartHandler( SessionStartHookInput input, diff --git a/docs/hooks/user-prompt-submitted.md b/docs/hooks/user-prompt-submitted.md index d5965f4a1..79e34249d 100644 --- a/docs/hooks/user-prompt-submitted.md +++ b/docs/hooks/user-prompt-submitted.md @@ -84,7 +84,7 @@ type UserPromptSubmittedHandler func( ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public delegate Task UserPromptSubmittedHandler( UserPromptSubmittedHookInput input, @@ -209,7 +209,7 @@ session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class UserPromptSubmittedExample { diff --git a/docs/integrations/microsoft-agent-framework.md b/docs/integrations/microsoft-agent-framework.md index 4da47104c..9480bcbcf 100644 --- a/docs/integrations/microsoft-agent-framework.md +++ b/docs/integrations/microsoft-agent-framework.md @@ -32,7 +32,7 @@ Install the Copilot SDK alongside the MAF integration package for your language: .NET ```shell -dotnet add package GitHub.Copilot.SDK +dotnet add package GitHub.Copilot dotnet add package Microsoft.Agents.AI.GitHub.Copilot --prerelease ``` @@ -74,7 +74,7 @@ Wrap the Copilot SDK client as a MAF agent with a single method call. The result ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Agents.AI; await using var copilotClient = new CopilotClient(); @@ -146,7 +146,7 @@ Extend your Copilot agent with custom function tools. Tools defined through the ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.AI; using Microsoft.Agents.AI; @@ -282,7 +282,7 @@ Run agents one after another, passing output from one to the next: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Orchestration; @@ -395,7 +395,7 @@ Run multiple agents in parallel and aggregate their results: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Orchestration; @@ -472,7 +472,7 @@ When building interactive applications, stream agent responses to show real-time ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Agents.AI; await using var copilotClient = new CopilotClient(); diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md index 9901d73c8..36f4cae9b 100644 --- a/docs/setup/backend-services.md +++ b/docs/setup/backend-services.md @@ -215,7 +215,7 @@ response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: message}) ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; var userId = "user1"; var message = "Hello"; diff --git a/docs/setup/choosing-a-setup-path.md b/docs/setup/choosing-a-setup-path.md index f1c4636c6..2fa27606a 100644 --- a/docs/setup/choosing-a-setup-path.md +++ b/docs/setup/choosing-a-setup-path.md @@ -133,7 +133,7 @@ All guides assume you have: * Node.js: `npm install @github/copilot-sdk` * Python: `pip install github-copilot-sdk` * Go: `go get github.com/github/copilot-sdk/go` (requires separate CLI installation) - * .NET: `dotnet add package GitHub.Copilot.SDK` + * .NET: `dotnet add package GitHub.Copilot` If you're brand new, start with the **[Getting Started tutorial](../getting-started.md)** first, then come back here for production configuration. diff --git a/docs/setup/github-oauth.md b/docs/setup/github-oauth.md index 8381e405c..6cba4a5b7 100644 --- a/docs/setup/github-oauth.md +++ b/docs/setup/github-oauth.md @@ -230,7 +230,7 @@ response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"} ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; CopilotClient CreateClientForUser(string userToken) => new CopilotClient(new CopilotClientOptions diff --git a/docs/troubleshooting/debugging.md b/docs/troubleshooting/debugging.md index cd78bd2e7..370c88f5c 100644 --- a/docs/troubleshooting/debugging.md +++ b/docs/troubleshooting/debugging.md @@ -73,7 +73,7 @@ client := copilot.NewClient(&copilot.ClientOptions{ ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.Logging; // Using ILogger diff --git a/docs/troubleshooting/mcp-debugging.md b/docs/troubleshooting/mcp-debugging.md index 34cab28c1..664826c6e 100644 --- a/docs/troubleshooting/mcp-debugging.md +++ b/docs/troubleshooting/mcp-debugging.md @@ -236,7 +236,7 @@ cd /expected/working/dir ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class McpDotnetConfigExample { @@ -287,7 +287,7 @@ public static class McpDotnetConfigExample ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; public static class McpNpxConfigExample { diff --git a/dotnet/README.md b/dotnet/README.md index 9330abf4c..da38bb117 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -7,7 +7,7 @@ SDK for programmatic control of GitHub Copilot CLI. ## Installation ```bash -dotnet add package GitHub.Copilot.SDK +dotnet add package GitHub.Copilot ``` ## Run the Samples @@ -27,7 +27,7 @@ dotnet run --file dotnet/samples/ManualToolResume.cs ## Quick Start ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; // Create and start client await using var client = new CopilotClient(); @@ -738,7 +738,7 @@ An `OnPermissionRequest` handler is optional when you create or resume a session Use the built-in `PermissionHandler.ApproveAll` helper to allow every tool call without any checks: ```csharp -using GitHub.Copilot.SDK; +using GitHub.Copilot; var session = await client.CreateSessionAsync(new SessionConfig { diff --git a/dotnet/samples/Chat.cs b/dotnet/samples/Chat.cs index 9e1be66c7..f748a4005 100644 --- a/dotnet/samples/Chat.cs +++ b/dotnet/samples/Chat.cs @@ -1,6 +1,6 @@ #:project ../src/GitHub.Copilot.SDK.csproj -using GitHub.Copilot.SDK; +using GitHub.Copilot; await using var client = new CopilotClient(); await using var session = await client.CreateSessionAsync(new SessionConfig diff --git a/dotnet/samples/ManualToolResume.cs b/dotnet/samples/ManualToolResume.cs index 07d310024..becda7444 100644 --- a/dotnet/samples/ManualToolResume.cs +++ b/dotnet/samples/ManualToolResume.cs @@ -1,8 +1,8 @@ #:project ../src/GitHub.Copilot.SDK.csproj using System.ComponentModel; -using GitHub.Copilot.SDK; -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot; +using GitHub.Copilot.Rpc; using Microsoft.Extensions.AI; var tool = ManualToolDeclaration(); diff --git a/dotnet/src/ActionDisposable.cs b/dotnet/src/ActionDisposable.cs index 815904c12..86230651e 100644 --- a/dotnet/src/ActionDisposable.cs +++ b/dotnet/src/ActionDisposable.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// A disposable that invokes an action when disposed. diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 59a30fbd1..abda77b7c 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; using Microsoft.Extensions.AI; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -17,7 +17,7 @@ using System.Text.Json.Serialization; using System.Text.RegularExpressions; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// Provides a client for interacting with the Copilot CLI server. @@ -1653,7 +1653,7 @@ private static JsonSerializerOptions CreateSerializerOptions() options.TypeInfoResolverChain.Add(TypesJsonContext.Default); options.TypeInfoResolverChain.Add(CopilotSession.SessionJsonContext.Default); options.TypeInfoResolverChain.Add(SessionEventsJsonContext.Default); - options.TypeInfoResolverChain.Add(SDK.Rpc.RpcJsonContext.Default); + options.TypeInfoResolverChain.Add(GitHub.Copilot.Rpc.RpcJsonContext.Default); options.MakeReadOnly(); diff --git a/dotnet/src/CopilotTool.cs b/dotnet/src/CopilotTool.cs index 59f1d126b..feed5be76 100644 --- a/dotnet/src/CopilotTool.cs +++ b/dotnet/src/CopilotTool.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.AI; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// Provides helpers for defining Copilot tools. diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 54ec6d48f..f1a7c0396 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -16,7 +16,7 @@ using System.Text.Json.Serialization; using System.Threading; -namespace GitHub.Copilot.SDK.Rpc; +namespace GitHub.Copilot.Rpc; /// Server liveness response, including the echoed message, current server timestamp, and protocol version. public sealed class PingResult @@ -6622,13 +6622,13 @@ public sealed class Converter : JsonConverter /// public override ModelPickerCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelPickerCategory value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerCategory)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerCategory)); } } } @@ -6690,13 +6690,13 @@ public sealed class Converter : JsonConverter /// public override ModelPickerPriceCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelPickerPriceCategory value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerPriceCategory)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerPriceCategory)); } } } @@ -6755,13 +6755,13 @@ public sealed class Converter : JsonConverter /// public override ModelPolicyState Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelPolicyState value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPolicyState)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPolicyState)); } } } @@ -6823,13 +6823,13 @@ public sealed class Converter : JsonConverter /// public override DiscoveredMcpServerType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, DiscoveredMcpServerType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(DiscoveredMcpServerType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(DiscoveredMcpServerType)); } } } @@ -6885,13 +6885,13 @@ public sealed class Converter : JsonConverter /// public override SessionFsSetProviderConventions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsSetProviderConventions value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSetProviderConventions)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSetProviderConventions)); } } } @@ -6948,13 +6948,13 @@ public sealed class Converter : JsonConverter public override ConnectedRemoteSessionMetadataKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ConnectedRemoteSessionMetadataKind value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ConnectedRemoteSessionMetadataKind)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ConnectedRemoteSessionMetadataKind)); } } } @@ -7011,13 +7011,13 @@ public sealed class Converter : JsonConverter /// public override SessionContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionContextHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionContextHostType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionContextHostType)); } } } @@ -7079,13 +7079,13 @@ public sealed class Converter : JsonConverter /// public override SendAgentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SendAgentMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAgentMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAgentMode)); } } } @@ -7144,13 +7144,13 @@ public sealed class Converter : JsonConverter /// public override SendAttachmentGithubReferenceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SendAttachmentGithubReferenceType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAttachmentGithubReferenceType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAttachmentGithubReferenceType)); } } } @@ -7206,13 +7206,13 @@ public sealed class Converter : JsonConverter /// public override SendMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SendMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendMode)); } } } @@ -7271,13 +7271,13 @@ public sealed class Converter : JsonConverter /// public override SessionLogLevel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionLogLevel value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionLogLevel)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionLogLevel)); } } } @@ -7348,13 +7348,13 @@ public sealed class Converter : JsonConverter /// public override AuthInfoType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AuthInfoType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AuthInfoType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AuthInfoType)); } } } @@ -7410,13 +7410,13 @@ public sealed class Converter : JsonConverter public override WorkspacesGetWorkspaceResultWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, WorkspacesGetWorkspaceResultWorkspaceHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); } } } @@ -7478,13 +7478,13 @@ public sealed class Converter : JsonConverter /// public override InstructionsSourcesLocation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, InstructionsSourcesLocation value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesLocation)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesLocation)); } } } @@ -7555,13 +7555,13 @@ public sealed class Converter : JsonConverter /// public override InstructionsSourcesType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, InstructionsSourcesType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesType)); } } } @@ -7630,13 +7630,13 @@ public sealed class Converter : JsonConverter /// public override AgentInfoSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AgentInfoSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AgentInfoSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AgentInfoSource)); } } } @@ -7693,13 +7693,13 @@ public sealed class Converter : JsonConverter /// public override TaskExecutionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, TaskExecutionMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskExecutionMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskExecutionMode)); } } } @@ -7765,13 +7765,13 @@ public sealed class Converter : JsonConverter /// public override TaskStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, TaskStatus value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskStatus)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskStatus)); } } } @@ -7828,13 +7828,13 @@ public sealed class Converter : JsonConverter /// public override TaskShellInfoAttachmentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, TaskShellInfoAttachmentMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskShellInfoAttachmentMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskShellInfoAttachmentMode)); } } } @@ -7894,13 +7894,13 @@ public sealed class Converter : JsonConverter /// public override McpSamplingExecutionAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpSamplingExecutionAction value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSamplingExecutionAction)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSamplingExecutionAction)); } } } @@ -7957,13 +7957,13 @@ public sealed class Converter : JsonConverter /// public override McpSetEnvValueModeDetails Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpSetEnvValueModeDetails value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSetEnvValueModeDetails)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSetEnvValueModeDetails)); } } } @@ -8020,13 +8020,13 @@ public sealed class Converter : JsonConverter /// public override OptionsUpdateEnvValueMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, OptionsUpdateEnvValueMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(OptionsUpdateEnvValueMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(OptionsUpdateEnvValueMode)); } } } @@ -8083,13 +8083,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionSource)); } } } @@ -8152,13 +8152,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionStatus value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionStatus)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionStatus)); } } } @@ -8211,13 +8211,13 @@ public sealed class Converter : JsonConverter /// public override SlashCommandInputCompletion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SlashCommandInputCompletion value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandInputCompletion)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandInputCompletion)); } } } @@ -8276,13 +8276,13 @@ public sealed class Converter : JsonConverter /// public override SlashCommandKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SlashCommandKind value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandKind)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandKind)); } } } @@ -8341,13 +8341,13 @@ public sealed class Converter : JsonConverter /// public override UIElicitationResponseAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UIElicitationResponseAction value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIElicitationResponseAction)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIElicitationResponseAction)); } } } @@ -8406,13 +8406,13 @@ public sealed class Converter : JsonConverter /// public override UIAutoModeSwitchResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UIAutoModeSwitchResponse value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIAutoModeSwitchResponse)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIAutoModeSwitchResponse)); } } } @@ -8474,13 +8474,13 @@ public sealed class Converter : JsonConverter /// public override UIExitPlanModeAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UIExitPlanModeAction value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIExitPlanModeAction)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIExitPlanModeAction)); } } } @@ -8536,13 +8536,13 @@ public sealed class Converter : JsonConverter public override PermissionsConfigureAdditionalContentExclusionPolicyScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionsConfigureAdditionalContentExclusionPolicyScope value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsConfigureAdditionalContentExclusionPolicyScope)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsConfigureAdditionalContentExclusionPolicyScope)); } } } @@ -8604,13 +8604,13 @@ public sealed class Converter : JsonConverter /// public override PermissionsSetApproveAllSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionsSetApproveAllSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsSetApproveAllSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsSetApproveAllSource)); } } } @@ -8666,13 +8666,13 @@ public sealed class Converter : JsonConverter /// public override PermissionsModifyRulesScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionsModifyRulesScope value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsModifyRulesScope)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsModifyRulesScope)); } } } @@ -8732,13 +8732,13 @@ public sealed class Converter : JsonConverter /// public override MetadataSnapshotCurrentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, MetadataSnapshotCurrentMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotCurrentMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotCurrentMode)); } } } @@ -8795,13 +8795,13 @@ public sealed class Converter : JsonConverter public override MetadataSnapshotRemoteMetadataTaskType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, MetadataSnapshotRemoteMetadataTaskType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotRemoteMetadataTaskType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotRemoteMetadataTaskType)); } } } @@ -8857,13 +8857,13 @@ public sealed class Converter : JsonConverter public override SessionMetadataSnapshotWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionMetadataSnapshotWorkspaceHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); } } } @@ -8920,13 +8920,13 @@ public sealed class Converter : JsonConverter public override SessionWorkingDirectoryContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionWorkingDirectoryContextHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionWorkingDirectoryContextHostType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionWorkingDirectoryContextHostType)); } } } @@ -8985,13 +8985,13 @@ public sealed class Converter : JsonConverter /// public override ShellKillSignal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ShellKillSignal value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShellKillSignal)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShellKillSignal)); } } } @@ -9048,13 +9048,13 @@ public sealed class Converter : JsonConverter /// public override QueuePendingItemsKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, QueuePendingItemsKind value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(QueuePendingItemsKind)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(QueuePendingItemsKind)); } } } @@ -9111,13 +9111,13 @@ public sealed class Converter : JsonConverter /// public override EventsCursorStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, EventsCursorStatus value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsCursorStatus)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsCursorStatus)); } } } @@ -9174,13 +9174,13 @@ public sealed class Converter : JsonConverter /// public override EventsAgentScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, EventsAgentScope value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsAgentScope)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsAgentScope)); } } } @@ -9240,13 +9240,13 @@ public sealed class Converter : JsonConverter /// public override RemoteSessionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, RemoteSessionMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(RemoteSessionMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(RemoteSessionMode)); } } } @@ -9302,13 +9302,13 @@ public sealed class Converter : JsonConverter /// public override SessionFsErrorCode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsErrorCode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsErrorCode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsErrorCode)); } } } @@ -9364,13 +9364,13 @@ public sealed class Converter : JsonConverter public override SessionFsReaddirWithTypesEntryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsReaddirWithTypesEntryType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsReaddirWithTypesEntryType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsReaddirWithTypesEntryType)); } } } @@ -9429,13 +9429,13 @@ public sealed class Converter : JsonConverter /// public override SessionFsSqliteQueryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsSqliteQueryType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSqliteQueryType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSqliteQueryType)); } } } @@ -12302,225 +12302,225 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func /// Provides the base class from which all session events derive. @@ -5345,13 +5345,13 @@ public sealed class Converter : JsonConverter /// public override WorkingDirectoryContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, WorkingDirectoryContextHostType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkingDirectoryContextHostType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkingDirectoryContextHostType)); } } } @@ -5409,13 +5409,13 @@ public sealed class Converter : JsonConverter /// public override ReasoningSummary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ReasoningSummary value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ReasoningSummary)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ReasoningSummary)); } } } @@ -5473,13 +5473,13 @@ public sealed class Converter : JsonConverter /// public override SessionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMode)); } } } @@ -5537,13 +5537,13 @@ public sealed class Converter : JsonConverter /// public override PlanChangedOperation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PlanChangedOperation value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PlanChangedOperation)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PlanChangedOperation)); } } } @@ -5598,13 +5598,13 @@ public sealed class Converter : JsonConverter /// public override WorkspaceFileChangedOperation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, WorkspaceFileChangedOperation value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspaceFileChangedOperation)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspaceFileChangedOperation)); } } } @@ -5659,13 +5659,13 @@ public sealed class Converter : JsonConverter /// public override HandoffSourceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, HandoffSourceType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(HandoffSourceType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(HandoffSourceType)); } } } @@ -5720,13 +5720,13 @@ public sealed class Converter : JsonConverter /// public override ShutdownType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ShutdownType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShutdownType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShutdownType)); } } } @@ -5787,13 +5787,13 @@ public sealed class Converter : JsonConverter /// public override UserMessageAgentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UserMessageAgentMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAgentMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAgentMode)); } } } @@ -5851,13 +5851,13 @@ public sealed class Converter : JsonConverter public override UserMessageAttachmentGithubReferenceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UserMessageAttachmentGithubReferenceType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAttachmentGithubReferenceType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAttachmentGithubReferenceType)); } } } @@ -5912,13 +5912,13 @@ public sealed class Converter : JsonConverter /// public override AssistantMessageToolRequestType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AssistantMessageToolRequestType value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantMessageToolRequestType)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantMessageToolRequestType)); } } } @@ -5979,13 +5979,13 @@ public sealed class Converter : JsonConverter /// public override AssistantUsageApiEndpoint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AssistantUsageApiEndpoint value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantUsageApiEndpoint)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantUsageApiEndpoint)); } } } @@ -6043,13 +6043,13 @@ public sealed class Converter : JsonConverter /// public override ModelCallFailureSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelCallFailureSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelCallFailureSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelCallFailureSource)); } } } @@ -6107,13 +6107,13 @@ public sealed class Converter : JsonConverter /// public override AbortReason Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AbortReason value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AbortReason)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AbortReason)); } } } @@ -6168,13 +6168,13 @@ public sealed class Converter : JsonConverter public override ToolExecutionCompleteContentResourceLinkIconTheme Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ToolExecutionCompleteContentResourceLinkIconTheme value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ToolExecutionCompleteContentResourceLinkIconTheme)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ToolExecutionCompleteContentResourceLinkIconTheme)); } } } @@ -6229,13 +6229,13 @@ public sealed class Converter : JsonConverter /// public override SystemMessageRole Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SystemMessageRole value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemMessageRole)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemMessageRole)); } } } @@ -6290,13 +6290,13 @@ public sealed class Converter : JsonConverter public override SystemNotificationAgentCompletedStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SystemNotificationAgentCompletedStatus value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemNotificationAgentCompletedStatus)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemNotificationAgentCompletedStatus)); } } } @@ -6351,13 +6351,13 @@ public sealed class Converter : JsonConverter /// public override PermissionRequestMemoryAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionRequestMemoryAction value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryAction)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryAction)); } } } @@ -6412,13 +6412,13 @@ public sealed class Converter : JsonConverter /// public override PermissionRequestMemoryDirection Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionRequestMemoryDirection value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryDirection)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryDirection)); } } } @@ -6476,13 +6476,13 @@ public sealed class Converter : JsonConverter public override PermissionPromptRequestPathAccessKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionPromptRequestPathAccessKind value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionPromptRequestPathAccessKind)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionPromptRequestPathAccessKind)); } } } @@ -6537,13 +6537,13 @@ public sealed class Converter : JsonConverter /// public override ElicitationRequestedMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ElicitationRequestedMode value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationRequestedMode)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationRequestedMode)); } } } @@ -6601,13 +6601,13 @@ public sealed class Converter : JsonConverter /// public override ElicitationCompletedAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ElicitationCompletedAction value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationCompletedAction)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationCompletedAction)); } } } @@ -6665,13 +6665,13 @@ public sealed class Converter : JsonConverter /// public override AutoModeSwitchResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AutoModeSwitchResponse value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AutoModeSwitchResponse)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AutoModeSwitchResponse)); } } } @@ -6732,13 +6732,13 @@ public sealed class Converter : JsonConverter /// public override ExitPlanModeAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExitPlanModeAction value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExitPlanModeAction)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExitPlanModeAction)); } } } @@ -6808,13 +6808,13 @@ public sealed class Converter : JsonConverter /// public override SkillSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SkillSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SkillSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SkillSource)); } } } @@ -6875,13 +6875,13 @@ public sealed class Converter : JsonConverter /// public override McpServerSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpServerSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerSource)); } } } @@ -6948,13 +6948,13 @@ public sealed class Converter : JsonConverter /// public override McpServerStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpServerStatus value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerStatus)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerStatus)); } } } @@ -7009,13 +7009,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionsLoadedExtensionSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionsLoadedExtensionSource value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionSource)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionSource)); } } } @@ -7076,13 +7076,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionsLoadedExtensionStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionsLoadedExtensionStatus value, JsonSerializerOptions options) { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionStatus)); + GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionStatus)); } } } diff --git a/dotnet/src/GitHub.Copilot.SDK.csproj b/dotnet/src/GitHub.Copilot.SDK.csproj index 933b51de2..7fa03ff4a 100644 --- a/dotnet/src/GitHub.Copilot.SDK.csproj +++ b/dotnet/src/GitHub.Copilot.SDK.csproj @@ -2,6 +2,7 @@ net8.0;net10.0;netstandard2.0 + GitHub.Copilot true 0.1.0 SDK for programmatic control of GitHub Copilot CLI diff --git a/dotnet/src/JsonRpc.cs b/dotnet/src/JsonRpc.cs index a97d0baed..866bb868f 100644 --- a/dotnet/src/JsonRpc.cs +++ b/dotnet/src/JsonRpc.cs @@ -14,7 +14,7 @@ using System.Text.Json.Serialization.Metadata; using System.Text.Unicode; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// A lightweight JSON-RPC 2.0 implementation covering only the features used diff --git a/dotnet/src/LoggingHelpers.cs b/dotnet/src/LoggingHelpers.cs index ca14ea3b9..a4f51cb65 100644 --- a/dotnet/src/LoggingHelpers.cs +++ b/dotnet/src/LoggingHelpers.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; using System.Diagnostics; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; internal static class LoggingHelpers { diff --git a/dotnet/src/MillisecondsTimeSpanConverter.cs b/dotnet/src/MillisecondsTimeSpanConverter.cs index 696d053dd..738d68648 100644 --- a/dotnet/src/MillisecondsTimeSpanConverter.cs +++ b/dotnet/src/MillisecondsTimeSpanConverter.cs @@ -6,7 +6,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// Converts between JSON numeric milliseconds and . [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/dotnet/src/PermissionHandlers.cs b/dotnet/src/PermissionHandlers.cs index a3d76bcb5..0e4af7eac 100644 --- a/dotnet/src/PermissionHandlers.cs +++ b/dotnet/src/PermissionHandlers.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// Provides pre-built permission request handlers. public static class PermissionHandler diff --git a/dotnet/src/SdkProtocolVersion.cs b/dotnet/src/SdkProtocolVersion.cs index 889af460b..659387b79 100644 --- a/dotnet/src/SdkProtocolVersion.cs +++ b/dotnet/src/SdkProtocolVersion.cs @@ -1,6 +1,6 @@ // Code generated by update-protocol-version.ts. DO NOT EDIT. -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// Provides the SDK protocol version. diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 6291b84c8..fc7d82675 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; using Microsoft.Extensions.AI; using Microsoft.Extensions.Logging; using System.Collections.Immutable; @@ -12,7 +12,7 @@ using System.Text.Json.Serialization; using System.Threading.Channels; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// Represents a single conversation session with the Copilot CLI. diff --git a/dotnet/src/SessionFsProvider.cs b/dotnet/src/SessionFsProvider.cs index cfe1d83ef..12dfc8770 100644 --- a/dotnet/src/SessionFsProvider.cs +++ b/dotnet/src/SessionFsProvider.cs @@ -2,9 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// /// Result of a SQLite query execution via . diff --git a/dotnet/src/Telemetry.cs b/dotnet/src/Telemetry.cs index 6bae267a9..893992e10 100644 --- a/dotnet/src/Telemetry.cs +++ b/dotnet/src/Telemetry.cs @@ -4,7 +4,7 @@ using System.Diagnostics; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; internal static class TelemetryHelpers { diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index fa26a9106..f8e80356b 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; using Microsoft.Extensions.AI; using Microsoft.Extensions.Logging; using System.ComponentModel; @@ -11,7 +11,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; internal static class GeneratedStringEnumJson { diff --git a/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs b/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs index 2245d5ebd..4b8fcc361 100644 --- a/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs +++ b/dotnet/src/UnixMillisecondsDateTimeOffsetConverter.cs @@ -6,7 +6,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; /// Converts between JSON numeric milliseconds-since-Unix-epoch and . [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/dotnet/test/ConnectionTokenTests.cs b/dotnet/test/ConnectionTokenTests.cs index bf2f08fc8..c1b4cd446 100644 --- a/dotnet/test/ConnectionTokenTests.cs +++ b/dotnet/test/ConnectionTokenTests.cs @@ -2,10 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; -namespace GitHub.Copilot.SDK.Test; +namespace GitHub.Copilot.Test; /// /// Custom fixture that spawns a CLI in TCP mode with an explicit connection token, so diff --git a/dotnet/test/E2E/AbortE2ETests.cs b/dotnet/test/E2E/AbortE2ETests.cs index fa8af0480..ea24610b7 100644 --- a/dotnet/test/E2E/AbortE2ETests.cs +++ b/dotnet/test/E2E/AbortE2ETests.cs @@ -7,7 +7,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Verifies that cleanly interrupts an active diff --git a/dotnet/test/E2E/AskUserE2ETests.cs b/dotnet/test/E2E/AskUserE2ETests.cs index cd79652d0..62faff367 100644 --- a/dotnet/test/E2E/AskUserE2ETests.cs +++ b/dotnet/test/E2E/AskUserE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class AskUserE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "ask_user", output) { diff --git a/dotnet/test/E2E/BuiltinToolsE2ETests.cs b/dotnet/test/E2E/BuiltinToolsE2ETests.cs index 76bbcf190..863331e9d 100644 --- a/dotnet/test/E2E/BuiltinToolsE2ETests.cs +++ b/dotnet/test/E2E/BuiltinToolsE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Smoke coverage for the Copilot CLI built-in tools (bash, view, edit, create_file, diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs index 0cc344c4f..8a13c4ac9 100644 --- a/dotnet/test/E2E/ClientE2ETests.cs +++ b/dotnet/test/E2E/ClientE2ETests.cs @@ -2,10 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; // These tests bypass E2ETestBase because they are about how the CLI subprocess is started // Other test classes should instead inherit from E2ETestBase diff --git a/dotnet/test/E2E/ClientLifecycleE2ETests.cs b/dotnet/test/E2E/ClientLifecycleE2ETests.cs index e0179cfbb..4b09c695d 100644 --- a/dotnet/test/E2E/ClientLifecycleE2ETests.cs +++ b/dotnet/test/E2E/ClientLifecycleE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class ClientLifecycleE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "client_lifecycle", output) diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index 785cf9d88..a3644a955 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -10,7 +10,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class ClientOptionsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "client_options", output) diff --git a/dotnet/test/E2E/ClientSessionManagementE2ETests.cs b/dotnet/test/E2E/ClientSessionManagementE2ETests.cs index f2d54a1d5..f6b126ce7 100644 --- a/dotnet/test/E2E/ClientSessionManagementE2ETests.cs +++ b/dotnet/test/E2E/ClientSessionManagementE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class ClientSessionManagementE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "client_api", output) diff --git a/dotnet/test/E2E/CommandsE2ETests.cs b/dotnet/test/E2E/CommandsE2ETests.cs index fd5e2165a..60a62bd58 100644 --- a/dotnet/test/E2E/CommandsE2ETests.cs +++ b/dotnet/test/E2E/CommandsE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class CommandsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "commands", output) diff --git a/dotnet/test/E2E/CompactionE2ETests.cs b/dotnet/test/E2E/CompactionE2ETests.cs index 70f1ff900..63d467535 100644 --- a/dotnet/test/E2E/CompactionE2ETests.cs +++ b/dotnet/test/E2E/CompactionE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class CompactionE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "compaction", output) { diff --git a/dotnet/test/E2E/ElicitationE2ETests.cs b/dotnet/test/E2E/ElicitationE2ETests.cs index 9e705d639..c14e11d55 100644 --- a/dotnet/test/E2E/ElicitationE2ETests.cs +++ b/dotnet/test/E2E/ElicitationE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class ElicitationE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "elicitation", output) diff --git a/dotnet/test/E2E/ErrorResilienceE2ETests.cs b/dotnet/test/E2E/ErrorResilienceE2ETests.cs index 0787b2a37..ab69e8c43 100644 --- a/dotnet/test/E2E/ErrorResilienceE2ETests.cs +++ b/dotnet/test/E2E/ErrorResilienceE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Verifies the SDK's behavior at the edges of the session lifecycle: sending or diff --git a/dotnet/test/E2E/EventFidelityE2ETests.cs b/dotnet/test/E2E/EventFidelityE2ETests.cs index fd2578b92..4504984f9 100644 --- a/dotnet/test/E2E/EventFidelityE2ETests.cs +++ b/dotnet/test/E2E/EventFidelityE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Verifies the shape and ordering of s emitted from the diff --git a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs index 5fe8b07a2..b16ee2b56 100644 --- a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs +++ b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs @@ -7,7 +7,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// E2E coverage for every handler exposed on : diff --git a/dotnet/test/E2E/HooksE2ETests.cs b/dotnet/test/E2E/HooksE2ETests.cs index 28301bf25..ab971c26e 100644 --- a/dotnet/test/E2E/HooksE2ETests.cs +++ b/dotnet/test/E2E/HooksE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class HooksE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "hooks", output) { diff --git a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs index 5c8831caf..0ae9c9a7d 100644 --- a/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs +++ b/dotnet/test/E2E/InMemorySessionFsSqliteHandler.cs @@ -3,11 +3,11 @@ *--------------------------------------------------------------------------------------------*/ using System.Collections.Concurrent; -using GitHub.Copilot.SDK; -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot; +using GitHub.Copilot.Rpc; using Microsoft.Data.Sqlite; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; internal record SqliteCall(string SessionId, string QueryType, string Query); diff --git a/dotnet/test/E2E/ModeHandlersE2ETests.cs b/dotnet/test/E2E/ModeHandlersE2ETests.cs index badbfc942..061967a3b 100644 --- a/dotnet/test/E2E/ModeHandlersE2ETests.cs +++ b/dotnet/test/E2E/ModeHandlersE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class ModeHandlersE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "mode_handlers", output) diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index d239cd433..559cfa6e3 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Custom fixture for multi-client commands/elicitation tests. diff --git a/dotnet/test/E2E/MultiClientE2ETests.cs b/dotnet/test/E2E/MultiClientE2ETests.cs index f88761dc2..981b812ea 100644 --- a/dotnet/test/E2E/MultiClientE2ETests.cs +++ b/dotnet/test/E2E/MultiClientE2ETests.cs @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.Collections.Concurrent; using System.ComponentModel; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Custom fixture for multi-client tests that uses TCP mode so a second client can connect. diff --git a/dotnet/test/E2E/MultiTurnE2ETests.cs b/dotnet/test/E2E/MultiTurnE2ETests.cs index 91e1d2ebe..4cfff92d4 100644 --- a/dotnet/test/E2E/MultiTurnE2ETests.cs +++ b/dotnet/test/E2E/MultiTurnE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Verifies that information produced in one turn (e.g., the contents of a file diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index b13b945c4..50f8778aa 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.ComponentModel; using Xunit; using Xunit.Abstractions; -using RpcPermissionDecisionApproveOnce = GitHub.Copilot.SDK.Rpc.PermissionDecisionApproveOnce; +using RpcPermissionDecisionApproveOnce = GitHub.Copilot.Rpc.PermissionDecisionApproveOnce; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class PendingWorkResumeE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "pending_work_resume", output) diff --git a/dotnet/test/E2E/PerSessionAuthE2ETests.cs b/dotnet/test/E2E/PerSessionAuthE2ETests.cs index f93da300c..42a433f9d 100644 --- a/dotnet/test/E2E/PerSessionAuthE2ETests.cs +++ b/dotnet/test/E2E/PerSessionAuthE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class PerSessionAuthE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "per-session-auth", output) { diff --git a/dotnet/test/E2E/PermissionE2ETests.cs b/dotnet/test/E2E/PermissionE2ETests.cs index edfe170f7..953ab1469 100644 --- a/dotnet/test/E2E/PermissionE2ETests.cs +++ b/dotnet/test/E2E/PermissionE2ETests.cs @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.Text.Json; using System.Text.Json.Serialization; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public partial class PermissionE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "permissions", output) { diff --git a/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs b/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs index 238299c02..241a978a9 100644 --- a/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs +++ b/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Targeted gap-filler tests for assorted RPC surface area where the previous suite covered diff --git a/dotnet/test/E2E/RpcAgentE2ETests.cs b/dotnet/test/E2E/RpcAgentE2ETests.cs index b64e858e4..cd60a2934 100644 --- a/dotnet/test/E2E/RpcAgentE2ETests.cs +++ b/dotnet/test/E2E/RpcAgentE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcAgentE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_agents", output) diff --git a/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs b/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs index 87336728c..9622553d1 100644 --- a/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs +++ b/dotnet/test/E2E/RpcEventSideEffectsE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Verifies that session-scoped RPC calls emit the expected side-effect session events. diff --git a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs index b353b97ae..c202571c1 100644 --- a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs +++ b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using System.Diagnostics; using Xunit; using Xunit.Abstractions; -using RpcExtension = GitHub.Copilot.SDK.Rpc.Extension; +using RpcExtension = GitHub.Copilot.Rpc.Extension; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// E2E coverage for the loaded-extensions code path in the runtime: when the diff --git a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs index f7a1bf574..1ac013301 100644 --- a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs @@ -4,10 +4,10 @@ using Xunit; using Xunit.Abstractions; -using RpcSkill = GitHub.Copilot.SDK.Rpc.Skill; -using RpcSkillList = GitHub.Copilot.SDK.Rpc.SkillList; +using RpcSkill = GitHub.Copilot.Rpc.Skill; +using RpcSkillList = GitHub.Copilot.Rpc.SkillList; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcMcpAndSkillsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_mcp_and_skills", output) diff --git a/dotnet/test/E2E/RpcMcpConfigE2ETests.cs b/dotnet/test/E2E/RpcMcpConfigE2ETests.cs index 179fc4828..d26e5535d 100644 --- a/dotnet/test/E2E/RpcMcpConfigE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpConfigE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; using System.Text.Json; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcMcpConfigE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_mcp_config", output) diff --git a/dotnet/test/E2E/RpcServerE2ETests.cs b/dotnet/test/E2E/RpcServerE2ETests.cs index b7d7e4624..39913060c 100644 --- a/dotnet/test/E2E/RpcServerE2ETests.cs +++ b/dotnet/test/E2E/RpcServerE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcServerE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_server", output) diff --git a/dotnet/test/E2E/RpcSessionStateE2ETests.cs b/dotnet/test/E2E/RpcSessionStateE2ETests.cs index 8092bbe3e..04ba27f54 100644 --- a/dotnet/test/E2E/RpcSessionStateE2ETests.cs +++ b/dotnet/test/E2E/RpcSessionStateE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcSessionStateE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_session_state", output) diff --git a/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs b/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs index 50e2d366f..a51fc7dae 100644 --- a/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs +++ b/dotnet/test/E2E/RpcShellAndFleetE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcShellAndFleetE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_shell_and_fleet", output) diff --git a/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs b/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs index 6b7a9c5e0..b6036b7b8 100644 --- a/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs +++ b/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Targeted edge-case tests for the shell RPC API (shell.exec, shell.kill). diff --git a/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs b/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs index 6e8860964..2ed338129 100644 --- a/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs +++ b/dotnet/test/E2E/RpcTasksAndHandlersE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class RpcTasksAndHandlersE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "rpc_tasks_and_handlers", output) @@ -101,7 +101,7 @@ await TestHelper.WaitForConditionAsync( Assert.Equal("general-purpose", task.AgentType); Assert.Equal("Reply with TASK_AGENT_DONE exactly.", task.Prompt); Assert.Equal("SDK background agent coverage", task.Description); - Assert.Equal(GitHub.Copilot.SDK.Rpc.TaskExecutionMode.Background, task.ExecutionMode); + Assert.Equal(GitHub.Copilot.Rpc.TaskExecutionMode.Background, task.ExecutionMode); Assert.False(task.CanPromoteToBackground.GetValueOrDefault()); Assert.NotEqual(default, task.StartedAt); @@ -114,8 +114,8 @@ await TestHelper.WaitForConditionAsync( task = await FindAgentTaskAsync(session, started.AgentId); return task?.LatestResponse?.Contains("TASK_AGENT_DONE", StringComparison.Ordinal) == true || task?.Result?.Contains("TASK_AGENT_DONE", StringComparison.Ordinal) == true - || task?.Status == GitHub.Copilot.SDK.Rpc.TaskStatus.Completed - || task?.Status == GitHub.Copilot.SDK.Rpc.TaskStatus.Failed; + || task?.Status == GitHub.Copilot.Rpc.TaskStatus.Completed + || task?.Status == GitHub.Copilot.Rpc.TaskStatus.Failed; }, timeout: TimeSpan.FromSeconds(60), timeoutMessage: $"Background agent task '{started.AgentId}' did not produce a final observable state."); @@ -123,7 +123,7 @@ await TestHelper.WaitForConditionAsync( Assert.NotNull(task); Assert.Contains("TASK_AGENT_DONE", task.LatestResponse ?? task.Result ?? string.Empty); - if (task.Status == GitHub.Copilot.SDK.Rpc.TaskStatus.Idle) + if (task.Status == GitHub.Copilot.Rpc.TaskStatus.Idle) { var cancel = await session.Rpc.Tasks.CancelAsync(started.AgentId); Assert.True(cancel.Cancelled); diff --git a/dotnet/test/E2E/SessionConfigE2ETests.cs b/dotnet/test/E2E/SessionConfigE2ETests.cs index c03315459..64f5518fb 100644 --- a/dotnet/test/E2E/SessionConfigE2ETests.cs +++ b/dotnet/test/E2E/SessionConfigE2ETests.cs @@ -2,13 +2,13 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using System.Text.Json; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SessionConfigE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "session_config", output) diff --git a/dotnet/test/E2E/SessionE2ETests.cs b/dotnet/test/E2E/SessionE2ETests.cs index 9e042633c..7711c86dc 100644 --- a/dotnet/test/E2E/SessionE2ETests.cs +++ b/dotnet/test/E2E/SessionE2ETests.cs @@ -2,15 +2,15 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.Collections.Concurrent; using System.ComponentModel; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SessionE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "session", output) { diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index aa124ea95..f0b22b1c6 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -2,13 +2,13 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SessionFsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "session_fs", output) diff --git a/dotnet/test/E2E/SessionFsSqliteE2ETests.cs b/dotnet/test/E2E/SessionFsSqliteE2ETests.cs index 9d0787b37..9caa624af 100644 --- a/dotnet/test/E2E/SessionFsSqliteE2ETests.cs +++ b/dotnet/test/E2E/SessionFsSqliteE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SessionFsSqliteE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "session_fs_sqlite", output) diff --git a/dotnet/test/E2E/SessionLifecycleE2ETests.cs b/dotnet/test/E2E/SessionLifecycleE2ETests.cs index 3864134cf..31532def2 100644 --- a/dotnet/test/E2E/SessionLifecycleE2ETests.cs +++ b/dotnet/test/E2E/SessionLifecycleE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// Lifecycle coverage at the level: listing diff --git a/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs b/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs index 475508065..9567c98be 100644 --- a/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs +++ b/dotnet/test/E2E/SessionMcpAndAgentConfigE2ETests.cs @@ -2,12 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Rpc; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Rpc; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SessionMcpAndAgentConfigE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "mcp_and_agents", output) { diff --git a/dotnet/test/E2E/SkillsE2ETests.cs b/dotnet/test/E2E/SkillsE2ETests.cs index 7da1d4b3e..76f84106f 100644 --- a/dotnet/test/E2E/SkillsE2ETests.cs +++ b/dotnet/test/E2E/SkillsE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SkillsE2ETests : E2ETestBase { diff --git a/dotnet/test/E2E/StreamingFidelityE2ETests.cs b/dotnet/test/E2E/StreamingFidelityE2ETests.cs index 119c76d0d..fec00f1cb 100644 --- a/dotnet/test/E2E/StreamingFidelityE2ETests.cs +++ b/dotnet/test/E2E/StreamingFidelityE2ETests.cs @@ -5,7 +5,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class StreamingFidelityE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "streaming_fidelity", output) { diff --git a/dotnet/test/E2E/SubagentHooksE2ETests.cs b/dotnet/test/E2E/SubagentHooksE2ETests.cs index 1a9c8ffa1..5c8543215 100644 --- a/dotnet/test/E2E/SubagentHooksE2ETests.cs +++ b/dotnet/test/E2E/SubagentHooksE2ETests.cs @@ -3,11 +3,11 @@ *--------------------------------------------------------------------------------------------*/ using System.Collections.Concurrent; -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SubagentHooksE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "subagent_hooks", output) diff --git a/dotnet/test/E2E/SuspendE2ETests.cs b/dotnet/test/E2E/SuspendE2ETests.cs index 3dadae4e8..8eb61da08 100644 --- a/dotnet/test/E2E/SuspendE2ETests.cs +++ b/dotnet/test/E2E/SuspendE2ETests.cs @@ -7,7 +7,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; /// /// E2E coverage for the session.suspend RPC. Suspend is a graceful shutdown diff --git a/dotnet/test/E2E/SystemMessageTransformE2ETests.cs b/dotnet/test/E2E/SystemMessageTransformE2ETests.cs index 5af704834..91f942190 100644 --- a/dotnet/test/E2E/SystemMessageTransformE2ETests.cs +++ b/dotnet/test/E2E/SystemMessageTransformE2ETests.cs @@ -2,11 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class SystemMessageTransformE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "system_message_transform", output) { diff --git a/dotnet/test/E2E/TelemetryExportE2ETests.cs b/dotnet/test/E2E/TelemetryExportE2ETests.cs index b4fced4e2..ceec2326e 100644 --- a/dotnet/test/E2E/TelemetryExportE2ETests.cs +++ b/dotnet/test/E2E/TelemetryExportE2ETests.cs @@ -2,13 +2,13 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.Text.Json; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public class TelemetryExportE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "telemetry", output) diff --git a/dotnet/test/E2E/ToolResultsE2ETests.cs b/dotnet/test/E2E/ToolResultsE2ETests.cs index fdc2654c6..75fd9488e 100644 --- a/dotnet/test/E2E/ToolResultsE2ETests.cs +++ b/dotnet/test/E2E/ToolResultsE2ETests.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.ComponentModel; using System.Text.Json; @@ -10,7 +10,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public partial class ToolResultsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "tool_results", output) { diff --git a/dotnet/test/E2E/ToolsE2ETests.cs b/dotnet/test/E2E/ToolsE2ETests.cs index 0a3581bbe..c36bf2294 100644 --- a/dotnet/test/E2E/ToolsE2ETests.cs +++ b/dotnet/test/E2E/ToolsE2ETests.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.AI; using System.Collections.ObjectModel; using System.ComponentModel; @@ -11,7 +11,7 @@ using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test.E2E; +namespace GitHub.Copilot.Test.E2E; public partial class ToolsE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "tools", output) { diff --git a/dotnet/test/GitHub.Copilot.SDK.Test.csproj b/dotnet/test/GitHub.Copilot.SDK.Test.csproj index cdff9b014..57f89bcd9 100644 --- a/dotnet/test/GitHub.Copilot.SDK.Test.csproj +++ b/dotnet/test/GitHub.Copilot.SDK.Test.csproj @@ -3,6 +3,7 @@ net8.0 net8.0;net472 + GitHub.Copilot.Test false true $(NoWarn);GHCP001 diff --git a/dotnet/test/Harness/CapiProxy.cs b/dotnet/test/Harness/CapiProxy.cs index 274055540..9b80651bc 100644 --- a/dotnet/test/Harness/CapiProxy.cs +++ b/dotnet/test/Harness/CapiProxy.cs @@ -10,7 +10,7 @@ using System.Text.Json.Serialization; using System.Text.RegularExpressions; -namespace GitHub.Copilot.SDK.Test.Harness; +namespace GitHub.Copilot.Test.Harness; public sealed partial class CapiProxy : IAsyncDisposable { diff --git a/dotnet/test/Harness/E2ETestBase.cs b/dotnet/test/Harness/E2ETestBase.cs index b11efa3d1..28cdd7f3d 100644 --- a/dotnet/test/Harness/E2ETestBase.cs +++ b/dotnet/test/Harness/E2ETestBase.cs @@ -2,14 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Microsoft.Extensions.Logging; using System.Data; using System.Reflection; using Xunit; using Xunit.Abstractions; -namespace GitHub.Copilot.SDK.Test; +namespace GitHub.Copilot.Test; public abstract class E2ETestBase : IClassFixture, IAsyncLifetime { diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index 5ed93ac4c..531d99255 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -7,7 +7,7 @@ using System.Runtime.CompilerServices; using System.Text.RegularExpressions; -namespace GitHub.Copilot.SDK.Test.Harness; +namespace GitHub.Copilot.Test.Harness; public sealed class E2ETestContext : IAsyncDisposable { diff --git a/dotnet/test/Harness/E2ETestFixture.cs b/dotnet/test/Harness/E2ETestFixture.cs index 07d1ef1b6..12f997073 100644 --- a/dotnet/test/Harness/E2ETestFixture.cs +++ b/dotnet/test/Harness/E2ETestFixture.cs @@ -2,10 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -using GitHub.Copilot.SDK.Test.Harness; +using GitHub.Copilot.Test.Harness; using Xunit; -namespace GitHub.Copilot.SDK.Test; +namespace GitHub.Copilot.Test; public class E2ETestFixture : IAsyncLifetime { diff --git a/dotnet/test/Harness/TestHelper.cs b/dotnet/test/Harness/TestHelper.cs index e974b7dd3..5d5839618 100644 --- a/dotnet/test/Harness/TestHelper.cs +++ b/dotnet/test/Harness/TestHelper.cs @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ -namespace GitHub.Copilot.SDK.Test.Harness; +namespace GitHub.Copilot.Test.Harness; public static class TestHelper { diff --git a/dotnet/test/Unit/ClientSessionLifetimeTests.cs b/dotnet/test/Unit/ClientSessionLifetimeTests.cs index ba8fb7d8d..239bda9da 100644 --- a/dotnet/test/Unit/ClientSessionLifetimeTests.cs +++ b/dotnet/test/Unit/ClientSessionLifetimeTests.cs @@ -11,7 +11,7 @@ using System.Text.Json; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; public sealed class ClientSessionLifetimeTests { diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 7c175fef5..3dd25ab3e 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -4,7 +4,7 @@ using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; public class CloneTests { diff --git a/dotnet/test/Unit/CopilotToolTests.cs b/dotnet/test/Unit/CopilotToolTests.cs index e1cb228fe..76ad0e425 100644 --- a/dotnet/test/Unit/CopilotToolTests.cs +++ b/dotnet/test/Unit/CopilotToolTests.cs @@ -7,7 +7,7 @@ using System.Text.Json; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; public class CopilotToolTests { diff --git a/dotnet/test/Unit/ForwardCompatibilityTests.cs b/dotnet/test/Unit/ForwardCompatibilityTests.cs index d0265c361..09133dfb5 100644 --- a/dotnet/test/Unit/ForwardCompatibilityTests.cs +++ b/dotnet/test/Unit/ForwardCompatibilityTests.cs @@ -6,7 +6,7 @@ using System.Text.Json.Serialization; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; /// /// Tests for forward-compatible handling of unknown session event types. @@ -240,7 +240,7 @@ public void RpcEnum_WithNonStringValue_ThrowsJsonException() [Fact] public void RpcEnum_DefaultValue_HasEmptyStringValue() { - GitHub.Copilot.SDK.SessionMode mode = default; + GitHub.Copilot.SessionMode mode = default; Assert.Equal(string.Empty, mode.Value); Assert.Equal(string.Empty, mode.ToString()); @@ -249,7 +249,7 @@ public void RpcEnum_DefaultValue_HasEmptyStringValue() [Fact] public void RpcEnum_DefaultValueSerialization_ThrowsJsonException() { - GitHub.Copilot.SDK.SessionMode mode = default; + GitHub.Copilot.SessionMode mode = default; var exception = Assert.Throws(() => JsonSerializer.Serialize( mode, @@ -304,5 +304,5 @@ public void FromJson_UnknownEventType_PreservesAgentIdNull() } } -[JsonSerializable(typeof(GitHub.Copilot.SDK.SessionMode))] +[JsonSerializable(typeof(GitHub.Copilot.SessionMode))] internal partial class ForwardCompatibilityJsonContext : JsonSerializerContext; diff --git a/dotnet/test/Unit/JsonRpcTests.cs b/dotnet/test/Unit/JsonRpcTests.cs index f4101956f..6c045c8eb 100644 --- a/dotnet/test/Unit/JsonRpcTests.cs +++ b/dotnet/test/Unit/JsonRpcTests.cs @@ -7,12 +7,12 @@ using System.Text.Json.Serialization.Metadata; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; /// /// Behavior tests for the SDK's hand-rolled JSON-RPC transport (params shape, serializer /// metadata, request/response routing, error propagation). Reflection is used to force -/// every generated JsonSerializable registration on the , +/// every generated JsonSerializable registration on the , /// which guards against regressions in the C# code generator (scripts/codegen/csharp.ts) /// silently dropping a registration. Functional behavior of individual RPC methods lives /// in the Rpc*Tests classes; this file owns transport- and serializer-shape concerns. @@ -160,7 +160,7 @@ public void Dispose() private sealed class JsonRpcReflection : IDisposable { private static readonly Type JsonRpcType = - typeof(CopilotClient).Assembly.GetType("GitHub.Copilot.SDK.JsonRpc", throwOnError: true)!; + typeof(CopilotClient).Assembly.GetType("GitHub.Copilot.JsonRpc", throwOnError: true)!; private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web) { diff --git a/dotnet/test/Unit/MSBuildTargetsTests.cs b/dotnet/test/Unit/MSBuildTargetsTests.cs index 745069ca4..a7d9cc025 100644 --- a/dotnet/test/Unit/MSBuildTargetsTests.cs +++ b/dotnet/test/Unit/MSBuildTargetsTests.cs @@ -7,7 +7,7 @@ using System.Text; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; /// /// Integration tests for the MSBuild targets shipped in diff --git a/dotnet/test/Unit/PermissionRequestResultKindTests.cs b/dotnet/test/Unit/PermissionRequestResultKindTests.cs index aed32a986..ce828e6ef 100644 --- a/dotnet/test/Unit/PermissionRequestResultKindTests.cs +++ b/dotnet/test/Unit/PermissionRequestResultKindTests.cs @@ -5,7 +5,7 @@ using System.Text.Json; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; public class PermissionRequestResultKindTests { diff --git a/dotnet/test/Unit/PublicDtoTests.cs b/dotnet/test/Unit/PublicDtoTests.cs index 76a0d80bf..473c312ba 100644 --- a/dotnet/test/Unit/PublicDtoTests.cs +++ b/dotnet/test/Unit/PublicDtoTests.cs @@ -7,7 +7,7 @@ using System.Text.Json; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; /// /// Reflection-based safety net that exercises the get/set surface of every public DTO in @@ -29,7 +29,7 @@ public void Public_Dto_Properties_Can_Be_Set_And_Read() .GetTypes() .Where(type => type is { IsClass: true, IsAbstract: false, IsPublic: true } && - type.Namespace?.StartsWith("GitHub.Copilot.SDK", StringComparison.Ordinal) == true && + type.Namespace?.StartsWith("GitHub.Copilot", StringComparison.Ordinal) == true && type.GetConstructor(Type.EmptyTypes) is not null) .OrderBy(type => type.FullName, StringComparer.Ordinal); diff --git a/dotnet/test/Unit/SerializationTests.cs b/dotnet/test/Unit/SerializationTests.cs index 6cb1c663f..c361987dd 100644 --- a/dotnet/test/Unit/SerializationTests.cs +++ b/dotnet/test/Unit/SerializationTests.cs @@ -7,9 +7,9 @@ #if !NET8_0_OR_GREATER using System.Runtime.Serialization; #endif -using GitHub.Copilot.SDK.Rpc; +using GitHub.Copilot.Rpc; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; /// /// Tests for JSON serialization compatibility with the SDK's configured options. diff --git a/dotnet/test/Unit/SessionEventSerializationTests.cs b/dotnet/test/Unit/SessionEventSerializationTests.cs index 3622821dc..3e6d4661f 100644 --- a/dotnet/test/Unit/SessionEventSerializationTests.cs +++ b/dotnet/test/Unit/SessionEventSerializationTests.cs @@ -5,7 +5,7 @@ using System.Text.Json; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; public class SessionEventSerializationTests { diff --git a/dotnet/test/Unit/TelemetryTests.cs b/dotnet/test/Unit/TelemetryTests.cs index 1a2fdc6e5..9229285b9 100644 --- a/dotnet/test/Unit/TelemetryTests.cs +++ b/dotnet/test/Unit/TelemetryTests.cs @@ -6,7 +6,7 @@ using System.Reflection; using Xunit; -namespace GitHub.Copilot.SDK.Test.Unit; +namespace GitHub.Copilot.Test.Unit; public class TelemetryTests { @@ -91,7 +91,7 @@ public void TelemetryHelpers_Restores_W3C_Trace_Context() private static T InvokeTelemetryHelper(string name, params object?[] args) { - var helperType = typeof(CopilotClient).Assembly.GetType("GitHub.Copilot.SDK.TelemetryHelpers", throwOnError: true)!; + var helperType = typeof(CopilotClient).Assembly.GetType("GitHub.Copilot.TelemetryHelpers", throwOnError: true)!; var method = helperType.GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic)!; return (T)method.Invoke(null, args)!; } diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 8fd6b6f58..fa57a0e34 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -569,12 +569,12 @@ function getOrCreateEnum( lines.push(` /// `); lines.push(` public override ${enumName} Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)`); lines.push(` {`); - lines.push(` return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert));`); + lines.push(` return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert));`); lines.push(` }`, ""); lines.push(` /// `); lines.push(` public override void Write(Utf8JsonWriter writer, ${enumName} value, JsonSerializerOptions options)`); lines.push(` {`); - lines.push(` GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(${enumName}));`); + lines.push(` GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(${enumName}));`); lines.push(` }`); lines.push(` }`); lines.push(`}`, ""); @@ -1283,7 +1283,7 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; -namespace GitHub.Copilot.SDK; +namespace GitHub.Copilot; `); // Base class with XML doc @@ -2243,7 +2243,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; -namespace GitHub.Copilot.SDK.Rpc; +namespace GitHub.Copilot.Rpc; `); for (const cls of classes) if (cls) lines.push(cls, ""); @@ -2264,7 +2264,7 @@ namespace GitHub.Copilot.SDK.Rpc; if (schemaFile !== "session-events.schema.json") continue; for (const name of [...names].sort()) { const typeName = typeToClassName(name); - lines.push(`[JsonSerializable(typeof(GitHub.Copilot.SDK.${typeName}), TypeInfoPropertyName = "SessionEvents${typeName}")]`); + lines.push(`[JsonSerializable(typeof(GitHub.Copilot.${typeName}), TypeInfoPropertyName = "SessionEvents${typeName}")]`); } } for (const t of typeNames) lines.push(`[JsonSerializable(typeof(${t}))]`); diff --git a/test/scenarios/auth/byok-anthropic/csharp/Program.cs b/test/scenarios/auth/byok-anthropic/csharp/Program.cs index 7e24c0fec..d55ee8f87 100644 --- a/test/scenarios/auth/byok-anthropic/csharp/Program.cs +++ b/test/scenarios/auth/byok-anthropic/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY"); var model = Environment.GetEnvironmentVariable("ANTHROPIC_MODEL") ?? "claude-sonnet-4-20250514"; diff --git a/test/scenarios/auth/byok-azure/csharp/Program.cs b/test/scenarios/auth/byok-azure/csharp/Program.cs index fc8589856..c51d48e05 100644 --- a/test/scenarios/auth/byok-azure/csharp/Program.cs +++ b/test/scenarios/auth/byok-azure/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); var apiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"); diff --git a/test/scenarios/auth/byok-ollama/csharp/Program.cs b/test/scenarios/auth/byok-ollama/csharp/Program.cs index f0b98e3c7..286f78754 100644 --- a/test/scenarios/auth/byok-ollama/csharp/Program.cs +++ b/test/scenarios/auth/byok-ollama/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var baseUrl = Environment.GetEnvironmentVariable("OLLAMA_BASE_URL") ?? "http://localhost:11434/v1"; var model = Environment.GetEnvironmentVariable("OLLAMA_MODEL") ?? "llama3.2:3b"; diff --git a/test/scenarios/auth/byok-openai/csharp/Program.cs b/test/scenarios/auth/byok-openai/csharp/Program.cs index 187c3c058..d95a972e7 100644 --- a/test/scenarios/auth/byok-openai/csharp/Program.cs +++ b/test/scenarios/auth/byok-openai/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY"); var model = Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "claude-haiku-4.5"; diff --git a/test/scenarios/auth/gh-app/csharp/Program.cs b/test/scenarios/auth/gh-app/csharp/Program.cs index f40349365..7dcbccd11 100644 --- a/test/scenarios/auth/gh-app/csharp/Program.cs +++ b/test/scenarios/auth/gh-app/csharp/Program.cs @@ -1,6 +1,6 @@ using System.Net.Http.Json; using System.Text.Json; -using GitHub.Copilot.SDK; +using GitHub.Copilot; // GitHub OAuth Device Flow var clientId = Environment.GetEnvironmentVariable("GITHUB_OAUTH_CLIENT_ID") diff --git a/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs b/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs index 317ce4e38..67b106ea8 100644 --- a/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs +++ b/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs @@ -1,5 +1,5 @@ using System.Text.Json; -using GitHub.Copilot.SDK; +using GitHub.Copilot; var port = Environment.GetEnvironmentVariable("PORT") ?? "8080"; var cliUrl = Environment.GetEnvironmentVariable("CLI_URL") diff --git a/test/scenarios/bundling/app-direct-server/csharp/Program.cs b/test/scenarios/bundling/app-direct-server/csharp/Program.cs index bbf42b940..e6e3561a3 100644 --- a/test/scenarios/bundling/app-direct-server/csharp/Program.cs +++ b/test/scenarios/bundling/app-direct-server/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; diff --git a/test/scenarios/bundling/container-proxy/csharp/Program.cs b/test/scenarios/bundling/container-proxy/csharp/Program.cs index bbf42b940..e6e3561a3 100644 --- a/test/scenarios/bundling/container-proxy/csharp/Program.cs +++ b/test/scenarios/bundling/container-proxy/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; diff --git a/test/scenarios/bundling/fully-bundled/csharp/Program.cs b/test/scenarios/bundling/fully-bundled/csharp/Program.cs index 8a93141f5..df042773f 100644 --- a/test/scenarios/bundling/fully-bundled/csharp/Program.cs +++ b/test/scenarios/bundling/fully-bundled/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/callbacks/hooks/csharp/Program.cs b/test/scenarios/callbacks/hooks/csharp/Program.cs index 7ea902f52..e8ae5bd95 100644 --- a/test/scenarios/callbacks/hooks/csharp/Program.cs +++ b/test/scenarios/callbacks/hooks/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var hookLog = new List(); diff --git a/test/scenarios/callbacks/permissions/csharp/Program.cs b/test/scenarios/callbacks/permissions/csharp/Program.cs index 2c1a650be..93dbe3508 100644 --- a/test/scenarios/callbacks/permissions/csharp/Program.cs +++ b/test/scenarios/callbacks/permissions/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var permissionLog = new List(); diff --git a/test/scenarios/callbacks/user-input/csharp/Program.cs b/test/scenarios/callbacks/user-input/csharp/Program.cs index a73b65155..73c4c8845 100644 --- a/test/scenarios/callbacks/user-input/csharp/Program.cs +++ b/test/scenarios/callbacks/user-input/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var inputLog = new List(); diff --git a/test/scenarios/modes/default/csharp/Program.cs b/test/scenarios/modes/default/csharp/Program.cs index 85f44ad20..f868b1f13 100644 --- a/test/scenarios/modes/default/csharp/Program.cs +++ b/test/scenarios/modes/default/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/modes/minimal/csharp/Program.cs b/test/scenarios/modes/minimal/csharp/Program.cs index 652bfcaa4..15aac333a 100644 --- a/test/scenarios/modes/minimal/csharp/Program.cs +++ b/test/scenarios/modes/minimal/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/prompts/attachments/csharp/Program.cs b/test/scenarios/prompts/attachments/csharp/Program.cs index 2868f9740..4f4974877 100644 --- a/test/scenarios/prompts/attachments/csharp/Program.cs +++ b/test/scenarios/prompts/attachments/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/prompts/reasoning-effort/csharp/Program.cs b/test/scenarios/prompts/reasoning-effort/csharp/Program.cs index bb01d0c81..186b843aa 100644 --- a/test/scenarios/prompts/reasoning-effort/csharp/Program.cs +++ b/test/scenarios/prompts/reasoning-effort/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/prompts/system-message/csharp/Program.cs b/test/scenarios/prompts/system-message/csharp/Program.cs index c0e92673c..e211e678b 100644 --- a/test/scenarios/prompts/system-message/csharp/Program.cs +++ b/test/scenarios/prompts/system-message/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var piratePrompt = "You are a pirate. Always respond in pirate speak. Say 'Arrr!' in every response. Use nautical terms and pirate slang throughout."; diff --git a/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs b/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs index bf4b33fba..8dfa75a3d 100644 --- a/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs +++ b/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; const string PiratePrompt = "You are a pirate. Always say Arrr!"; const string RobotPrompt = "You are a robot. Always say BEEP BOOP!"; diff --git a/test/scenarios/sessions/infinite-sessions/csharp/Program.cs b/test/scenarios/sessions/infinite-sessions/csharp/Program.cs index 82c0f3001..b3c6169c1 100644 --- a/test/scenarios/sessions/infinite-sessions/csharp/Program.cs +++ b/test/scenarios/sessions/infinite-sessions/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/sessions/session-resume/csharp/Program.cs b/test/scenarios/sessions/session-resume/csharp/Program.cs index 31f233313..c5a8f93ef 100644 --- a/test/scenarios/sessions/session-resume/csharp/Program.cs +++ b/test/scenarios/sessions/session-resume/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/sessions/streaming/csharp/Program.cs b/test/scenarios/sessions/streaming/csharp/Program.cs index 5dcc3182b..a2445e22b 100644 --- a/test/scenarios/sessions/streaming/csharp/Program.cs +++ b/test/scenarios/sessions/streaming/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var options = new CopilotClientOptions { diff --git a/test/scenarios/tools/custom-agents/csharp/Program.cs b/test/scenarios/tools/custom-agents/csharp/Program.cs index 90721c2a2..ecf1a12fe 100644 --- a/test/scenarios/tools/custom-agents/csharp/Program.cs +++ b/test/scenarios/tools/custom-agents/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.AI; var cliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"); diff --git a/test/scenarios/tools/mcp-servers/csharp/Program.cs b/test/scenarios/tools/mcp-servers/csharp/Program.cs index 739ca058b..6aea8fdab 100644 --- a/test/scenarios/tools/mcp-servers/csharp/Program.cs +++ b/test/scenarios/tools/mcp-servers/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/tools/no-tools/csharp/Program.cs b/test/scenarios/tools/no-tools/csharp/Program.cs index 619b05266..4e383a239 100644 --- a/test/scenarios/tools/no-tools/csharp/Program.cs +++ b/test/scenarios/tools/no-tools/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; const string SystemPrompt = """ You are a minimal assistant with no tools available. diff --git a/test/scenarios/tools/skills/csharp/Program.cs b/test/scenarios/tools/skills/csharp/Program.cs index 4fb229df9..784d9ef50 100644 --- a/test/scenarios/tools/skills/csharp/Program.cs +++ b/test/scenarios/tools/skills/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/tools/tool-filtering/csharp/Program.cs b/test/scenarios/tools/tool-filtering/csharp/Program.cs index 30bc29881..66c663166 100644 --- a/test/scenarios/tools/tool-filtering/csharp/Program.cs +++ b/test/scenarios/tools/tool-filtering/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/tools/tool-overrides/csharp/Program.cs b/test/scenarios/tools/tool-overrides/csharp/Program.cs index 9224b3aee..d02cf5bd6 100644 --- a/test/scenarios/tools/tool-overrides/csharp/Program.cs +++ b/test/scenarios/tools/tool-overrides/csharp/Program.cs @@ -1,5 +1,5 @@ using System.ComponentModel; -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.AI; using var client = new CopilotClient(new CopilotClientOptions diff --git a/test/scenarios/tools/virtual-filesystem/csharp/Program.cs b/test/scenarios/tools/virtual-filesystem/csharp/Program.cs index 8e2566ee5..f758eb92f 100644 --- a/test/scenarios/tools/virtual-filesystem/csharp/Program.cs +++ b/test/scenarios/tools/virtual-filesystem/csharp/Program.cs @@ -1,5 +1,5 @@ using System.ComponentModel; -using GitHub.Copilot.SDK; +using GitHub.Copilot; using Microsoft.Extensions.AI; // In-memory virtual filesystem diff --git a/test/scenarios/transport/reconnect/csharp/Program.cs b/test/scenarios/transport/reconnect/csharp/Program.cs index b79246eda..bbc0022b3 100644 --- a/test/scenarios/transport/reconnect/csharp/Program.cs +++ b/test/scenarios/transport/reconnect/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; diff --git a/test/scenarios/transport/stdio/csharp/Program.cs b/test/scenarios/transport/stdio/csharp/Program.cs index 8a93141f5..df042773f 100644 --- a/test/scenarios/transport/stdio/csharp/Program.cs +++ b/test/scenarios/transport/stdio/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { diff --git a/test/scenarios/transport/tcp/csharp/Program.cs b/test/scenarios/transport/tcp/csharp/Program.cs index 6e85aae3d..4cd007a8f 100644 --- a/test/scenarios/transport/tcp/csharp/Program.cs +++ b/test/scenarios/transport/tcp/csharp/Program.cs @@ -1,4 +1,4 @@ -using GitHub.Copilot.SDK; +using GitHub.Copilot; var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; From 199189c35737c9c5454fa0d71ce84bae64a55ffa Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:41:58 +0100 Subject: [PATCH 30/40] Fix local test runs --- dotnet/test/Harness/E2ETestContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index 531d99255..1c4eb6125 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -197,7 +197,7 @@ public IReadOnlyDictionary GetEnvironment() env["GITHUB_ENTERPRISE_TOKEN"] = ""; } - env["GITHUB_TOKEN"] = env["GH_TOKEN"] = ""; + env["GITHUB_TOKEN"] = env["GH_TOKEN"] = DefaultGitHubToken; return env!; } From cc3e9d1dcf1baae280eab9f5400e8528c05cd52d Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:48:07 +0100 Subject: [PATCH 31/40] Drop unused uriConn binding in Client.cs is-check Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Client.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index abda77b7c..2999f4897 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -224,7 +224,7 @@ async Task StartCoreAsync(CancellationToken ct) try { - if (_connection is UriRuntimeConnection uriConn) + if (_connection is UriRuntimeConnection) { // External runtime _actualPort = _optionsPort; From c721e403607a91fa466b03803179429e802fbb10 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:52:59 +0100 Subject: [PATCH 32/40] Address Copilot review feedback - README: fix Custom Permission Handler signature (PermissionInvocation, not ToolInvocation). - Client.cs StartAsync: remove empty in remarks and the misleading 'Reset disposed flag for restart scenarios' comment (no reset actually happens). - Indent the Connection = RuntimeConnection.Uri(...) line inside object initializers in backend-services.md and getting-started.md C# snippets for consistency. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/getting-started.md | 2 +- docs/setup/backend-services.md | 4 ++-- dotnet/README.md | 2 +- dotnet/src/Client.cs | 5 ----- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 9e6e5f357..51490c67e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2071,7 +2071,7 @@ using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { -Connection = RuntimeConnection.Uri("localhost:4321"), + Connection = RuntimeConnection.Uri("localhost:4321"), }); // Use the client normally diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md index 36f4cae9b..b6d15c44b 100644 --- a/docs/setup/backend-services.md +++ b/docs/setup/backend-services.md @@ -222,7 +222,7 @@ var message = "Hello"; var client = new CopilotClient(new CopilotClientOptions { -Connection = RuntimeConnection.Uri("localhost:4321"), + Connection = RuntimeConnection.Uri("localhost:4321"), }); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -239,7 +239,7 @@ var response = await session.SendAndWaitAsync( ```csharp var client = new CopilotClient(new CopilotClientOptions { -Connection = RuntimeConnection.Uri("localhost:4321"), + Connection = RuntimeConnection.Uri("localhost:4321"), }); await using var session = await client.CreateSessionAsync(new SessionConfig diff --git a/dotnet/README.md b/dotnet/README.md index da38bb117..f86be66e7 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -749,7 +749,7 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Custom Permission Handler -Provide your own permission handler (`Func>`) to inspect each request and apply custom logic: +Provide your own permission handler (`Func>`) to inspect each request and apply custom logic: ```csharp var session = await client.CreateSessionAsync(new SessionConfig diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 2999f4897..7a0ffb328 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -195,12 +195,8 @@ private static Uri ParseRuntimeUrl(string url) /// A that can be used to cancel the operation. /// A representing the asynchronous operation. /// - /// /// If the server is not already running and the client is configured to spawn one (default), it will be started. /// If connecting to an external runtime (via RuntimeConnection.Uri), only establishes the connection. - /// - /// - /// /// /// /// @@ -216,7 +212,6 @@ public Task StartAsync(CancellationToken cancellationToken = default) async Task StartCoreAsync(CancellationToken ct) { _logger.LogDebug("Starting Copilot client"); - // Reset disposed flag for restart scenarios var startTimestamp = Stopwatch.GetTimestamp(); Connection? connection = null; From ab570c322f9c3971a4e371c8c79b3cb8e21fb93d Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Wed, 20 May 2026 19:54:46 +0100 Subject: [PATCH 33/40] Docs validation: prepend 'using GitHub.Copilot;' after namespace rename The validation extractor auto-injects a using directive into every C# snippet; update it to match the new namespace. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- scripts/docs-validation/extract.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/docs-validation/extract.ts b/scripts/docs-validation/extract.ts index 879873048..0b0879db1 100644 --- a/scripts/docs-validation/extract.ts +++ b/scripts/docs-validation/extract.ts @@ -302,8 +302,8 @@ function wrapCodeForValidation(block: CodeBlock): string { } // Always ensure SDK using is present - if (!usings.some(u => u.includes("GitHub.Copilot.SDK"))) { - usings.push("using GitHub.Copilot.SDK;"); + if (!usings.some(u => u.includes("GitHub.Copilot"))) { + usings.push("using GitHub.Copilot;"); } // Generate a unique class name based on block location @@ -336,8 +336,8 @@ ${indentedCode} } } else { // Has structure, but may still need using directive - if (!code.includes("using GitHub.Copilot.SDK;")) { - code = "using GitHub.Copilot.SDK;\n" + code; + if (!code.includes("using GitHub.Copilot;")) { + code = "using GitHub.Copilot;\n" + code; } } } From eeb9b4acc9206beb8096696da376405ace998315 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 21 May 2026 09:49:17 +0100 Subject: [PATCH 34/40] Rename RuntimeConnection factories: Stdio/Tcp/Uri -> ForStdio/ForTcp/ForUri Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/getting-started.md | 2 +- docs/setup/backend-services.md | 4 +-- docs/setup/local-cli.md | 2 +- docs/troubleshooting/debugging.md | 2 +- dotnet/README.md | 14 ++++---- dotnet/src/Client.cs | 12 +++---- dotnet/src/Types.cs | 20 +++++------ dotnet/test/ConnectionTokenTests.cs | 6 ++-- dotnet/test/E2E/ClientE2ETests.cs | 28 +++++++-------- dotnet/test/E2E/ClientOptionsE2ETests.cs | 20 +++++------ .../MultiClientCommandsElicitationE2ETests.cs | 6 ++-- dotnet/test/E2E/MultiClientE2ETests.cs | 6 ++-- dotnet/test/E2E/PendingWorkResumeE2ETests.cs | 36 +++++++++---------- .../test/E2E/RpcExtensionsLoadedE2ETests.cs | 2 +- dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs | 4 +-- dotnet/test/E2E/SessionFsE2ETests.cs | 6 ++-- dotnet/test/E2E/SuspendE2ETests.cs | 6 ++-- dotnet/test/Harness/E2ETestBase.cs | 2 +- dotnet/test/Harness/E2ETestFixture.cs | 2 +- .../test/Unit/ClientSessionLifetimeTests.cs | 14 ++++---- dotnet/test/Unit/CloneTests.cs | 4 +-- .../auth/byok-anthropic/csharp/Program.cs | 2 +- .../auth/byok-azure/csharp/Program.cs | 2 +- .../auth/byok-ollama/csharp/Program.cs | 2 +- .../auth/byok-openai/csharp/Program.cs | 2 +- test/scenarios/auth/gh-app/csharp/Program.cs | 2 +- .../app-backend-to-server/csharp/Program.cs | 2 +- .../app-direct-server/csharp/Program.cs | 2 +- .../container-proxy/csharp/Program.cs | 2 +- .../bundling/fully-bundled/csharp/Program.cs | 2 +- .../callbacks/hooks/csharp/Program.cs | 2 +- .../callbacks/permissions/csharp/Program.cs | 2 +- .../callbacks/user-input/csharp/Program.cs | 2 +- .../scenarios/modes/default/csharp/Program.cs | 2 +- .../scenarios/modes/minimal/csharp/Program.cs | 2 +- .../prompts/attachments/csharp/Program.cs | 2 +- .../reasoning-effort/csharp/Program.cs | 2 +- .../prompts/system-message/csharp/Program.cs | 2 +- .../concurrent-sessions/csharp/Program.cs | 2 +- .../infinite-sessions/csharp/Program.cs | 2 +- .../sessions/session-resume/csharp/Program.cs | 2 +- .../sessions/streaming/csharp/Program.cs | 2 +- .../tools/custom-agents/csharp/Program.cs | 2 +- .../tools/mcp-servers/csharp/Program.cs | 2 +- .../tools/no-tools/csharp/Program.cs | 2 +- test/scenarios/tools/skills/csharp/Program.cs | 2 +- .../tools/tool-filtering/csharp/Program.cs | 2 +- .../tools/tool-overrides/csharp/Program.cs | 2 +- .../virtual-filesystem/csharp/Program.cs | 2 +- .../transport/reconnect/csharp/Program.cs | 2 +- .../transport/stdio/csharp/Program.cs | 2 +- .../scenarios/transport/tcp/csharp/Program.cs | 2 +- 52 files changed, 130 insertions(+), 130 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 51490c67e..b5d7caa21 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2071,7 +2071,7 @@ using GitHub.Copilot; using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Uri("localhost:4321"), + Connection = RuntimeConnection.ForUri("localhost:4321"), }); // Use the client normally diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md index b6d15c44b..d9dd508e5 100644 --- a/docs/setup/backend-services.md +++ b/docs/setup/backend-services.md @@ -222,7 +222,7 @@ var message = "Hello"; var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Uri("localhost:4321"), + Connection = RuntimeConnection.ForUri("localhost:4321"), }); await using var session = await client.CreateSessionAsync(new SessionConfig @@ -239,7 +239,7 @@ var response = await session.SendAndWaitAsync( ```csharp var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Uri("localhost:4321"), + Connection = RuntimeConnection.ForUri("localhost:4321"), }); await using var session = await client.CreateSessionAsync(new SessionConfig diff --git a/docs/setup/local-cli.md b/docs/setup/local-cli.md index 95c6b230a..e7da4d937 100644 --- a/docs/setup/local-cli.md +++ b/docs/setup/local-cli.md @@ -139,7 +139,7 @@ if response != nil { ```csharp var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: "/usr/local/bin/copilot"), + Connection = RuntimeConnection.ForStdio(path: "/usr/local/bin/copilot"), }); await using var session = await client.CreateSessionAsync( diff --git a/docs/troubleshooting/debugging.md b/docs/troubleshooting/debugging.md index 370c88f5c..f01beafc7 100644 --- a/docs/troubleshooting/debugging.md +++ b/docs/troubleshooting/debugging.md @@ -164,7 +164,7 @@ func main() { ```csharp var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(args: new[] { "--log-dir", "/path/to/logs" }) + Connection = RuntimeConnection.ForStdio(args: new[] { "--log-dir", "/path/to/logs" }) }); ``` diff --git a/dotnet/README.md b/dotnet/README.md index f86be66e7..f01d87474 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -72,24 +72,24 @@ new CopilotClient(CopilotClientOptions? options = null) **Options:** -- `Connection` - How to connect to the Copilot runtime. Defaults to `null` (equivalent to `RuntimeConnection.Stdio()` with the bundled runtime). See "RuntimeConnection" below. +- `Connection` - How to connect to the Copilot runtime. Defaults to `null` (equivalent to `RuntimeConnection.ForStdio()` with the bundled runtime). See "RuntimeConnection" below. - `LogLevel` - Runtime log level. Accepts well-known values `CopilotLogLevel.None`, `Error`, `Warning`, `Info`, `Debug`, `All`. Defaults to null (the runtime's own default). - `WorkingDirectory` - Working directory for the runtime process. -- `BaseDirectory` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned runtime process. When not set, the runtime defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when connecting via `RuntimeConnection.Uri(...)`. +- `BaseDirectory` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned runtime process. When not set, the runtime defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when connecting via `RuntimeConnection.ForUri(...)`. - `EnableRemoteSessions` - Enables remote-session features. - `Environment` - Environment variables to pass to the runtime process. - `Logger` - `ILogger` instance for SDK logging. - `GitHubToken` - GitHub token for authentication. When provided, takes priority over other auth methods. -- `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `RuntimeConnection.Uri(...)`. +- `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `RuntimeConnection.ForUri(...)`. - `Telemetry` - OpenTelemetry configuration for the runtime process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below. #### RuntimeConnection `CopilotClientOptions.Connection` describes how the SDK reaches a Copilot runtime. There are three flavors, all constructed via static factories: -- `RuntimeConnection.Stdio(path?, args?)` — spawns the runtime as a child process and communicates over stdio. This is the default when `Connection` is null. -- `RuntimeConnection.Tcp(port = 0, connectionToken?, path?, args?)` — spawns the runtime as a child process listening on a TCP port. `port = 0` auto-allocates; if a non-zero port is already in use, startup fails (no fallback). Use `CopilotClient.RuntimePort` after `StartAsync` to read the assigned port. `connectionToken` is required if other clients will connect via `RuntimeConnection.Uri(...)`. -- `RuntimeConnection.Uri(url, connectionToken?)` — connects to an already-running runtime at `url` (e.g., `"localhost:8080"`). Does not spawn a process. +- `RuntimeConnection.ForStdio(path?, args?)` — spawns the runtime as a child process and communicates over stdio. This is the default when `Connection` is null. +- `RuntimeConnection.ForTcp(port = 0, connectionToken?, path?, args?)` — spawns the runtime as a child process listening on a TCP port. `port = 0` auto-allocates; if a non-zero port is already in use, startup fails (no fallback). Use `CopilotClient.RuntimePort` after `StartAsync` to read the assigned port. `connectionToken` is required if other clients will connect via `RuntimeConnection.ForUri(...)`. +- `RuntimeConnection.ForUri(url, connectionToken?)` — connects to an already-running runtime at `url` (e.g., `"localhost:8080"`). Does not spawn a process. #### Methods @@ -987,7 +987,7 @@ catch (Exception ex) ## Requirements - .NET 8.0 or later -- GitHub Copilot CLI installed and in PATH (or provide custom `Connection = RuntimeConnection.Stdio(path: ...)`) +- GitHub Copilot CLI installed and in PATH (or provide custom `Connection = RuntimeConnection.ForStdio(path: ...)`) ## License diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 7a0ffb328..11f8c90c9 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -115,12 +115,12 @@ private sealed record LifecycleSubscription(Type EventType, Action @@ -128,7 +128,7 @@ private sealed record LifecycleSubscription(Type EventType, ActionA representing the asynchronous operation. /// /// If the server is not already running and the client is configured to spawn one (default), it will be started. - /// If connecting to an external runtime (via RuntimeConnection.Uri), only establishes the connection. + /// If connecting to an external runtime (via RuntimeConnection.ForUri), only establishes the connection. /// /// /// @@ -1335,7 +1335,7 @@ private static bool IsUnsupportedConnectMethod(RemoteRpcException ex) var cliPath = childProcessConnection.Path ?? envCliPath ?? GetBundledCliPath(out var searchedPath) - ?? throw new InvalidOperationException($"Copilot runtime not found at '{searchedPath}'. Ensure the SDK NuGet package was restored correctly or provide an explicit RuntimeConnection.Stdio(path: ...) / RuntimeConnection.Tcp(path: ...)."); + ?? throw new InvalidOperationException($"Copilot runtime not found at '{searchedPath}'. Ensure the SDK NuGet package was restored correctly or provide an explicit RuntimeConnection.ForStdio(path: ...) / RuntimeConnection.ForTcp(path: ...)."); var cliPathSource = childProcessConnection.Path is not null ? "Options" : envCliPath is not null ? "Environment" : "Bundled"; var args = new List(); diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index f8e80356b..9cc070f78 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -120,7 +120,7 @@ internal RuntimeConnection() { } /// /// Path to the runtime executable. When null, the bundled runtime is used. /// Extra command-line arguments to pass to the runtime process. - public static StdioRuntimeConnection Stdio(string? path = null, IList? args = null) + public static StdioRuntimeConnection ForStdio(string? path = null, IList? args = null) => new() { Path = path, Args = args }; /// @@ -132,7 +132,7 @@ public static StdioRuntimeConnection Stdio(string? path = null, IList? a /// When null, a GUID is generated automatically. /// Path to the runtime executable. When null, the bundled runtime is used. /// Extra command-line arguments to pass to the runtime process. - public static TcpRuntimeConnection Tcp(int port = 0, string? connectionToken = null, string? path = null, IList? args = null) + public static TcpRuntimeConnection ForTcp(int port = 0, string? connectionToken = null, string? path = null, IList? args = null) => new() { Port = port, ConnectionToken = connectionToken, Path = path, Args = args }; /// @@ -140,7 +140,7 @@ public static TcpRuntimeConnection Tcp(int port = 0, string? connectionToken = n /// /// URL of the runtime to connect to. Accepts "port", "host:port", or a full URL. /// Optional shared secret to authenticate the connection. - public static UriRuntimeConnection Uri(string url, string? connectionToken = null) + public static UriRuntimeConnection ForUri(string url, string? connectionToken = null) => new() { Url = url, ConnectionToken = connectionToken }; } @@ -160,7 +160,7 @@ internal ChildProcessRuntimeConnection() { } /// /// Spawns a runtime child process and communicates over stdin/stdout. Construct via -/// . +/// . /// public sealed class StdioRuntimeConnection : ChildProcessRuntimeConnection { @@ -169,7 +169,7 @@ internal StdioRuntimeConnection() { } /// /// Spawns a runtime child process listening on a TCP socket. Construct via -/// . +/// . /// public sealed class TcpRuntimeConnection : ChildProcessRuntimeConnection { @@ -190,7 +190,7 @@ internal TcpRuntimeConnection() { } /// /// Connects to an already-running runtime at the specified URL. Construct via -/// . +/// . /// public sealed class UriRuntimeConnection : RuntimeConnection { @@ -241,7 +241,7 @@ private CopilotClientOptions(CopilotClientOptions? other) /// /// How to connect to the runtime. When null, the default is - /// with the bundled runtime. + /// with the bundled runtime. /// public RuntimeConnection? Connection { get; set; } @@ -255,7 +255,7 @@ private CopilotClientOptions(CopilotClientOptions? other) /// Sets the COPILOT_HOME environment variable on the spawned runtime. /// When , the runtime defaults to ~/.copilot. /// Ignored when connecting to an existing runtime via - /// . + /// . /// public string? BaseDirectory { get; set; } @@ -317,7 +317,7 @@ private CopilotClientOptions(CopilotClientOptions? other) /// Sessions without activity for this duration are automatically cleaned up. /// Set to 0 or leave as to disable (sessions live indefinitely). /// This option is only used when the SDK spawns the runtime; it is ignored - /// when connecting to an external runtime via . + /// when connecting to an external runtime via . /// public int? SessionIdleTimeoutSeconds { get; set; } @@ -326,7 +326,7 @@ private CopilotClientOptions(CopilotClientOptions? other) /// When true, sessions in a GitHub repository working directory are /// accessible from GitHub web and mobile. /// This option is only used when the SDK spawns the runtime; it is ignored - /// when connecting to an external runtime via . + /// when connecting to an external runtime via . /// public bool EnableRemoteSessions { get; set; } diff --git a/dotnet/test/ConnectionTokenTests.cs b/dotnet/test/ConnectionTokenTests.cs index c1b4cd446..524ff2586 100644 --- a/dotnet/test/ConnectionTokenTests.cs +++ b/dotnet/test/ConnectionTokenTests.cs @@ -22,7 +22,7 @@ public class ConnectionTokenTestFixture : IAsyncLifetime public async Task InitializeAsync() { Ctx = await E2ETestContext.CreateAsync(); - GoodClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: Token) }); + GoodClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: Token) }); await GoodClient.StartAsync(); Port = GoodClient.RuntimePort @@ -59,7 +59,7 @@ public async Task Connects_With_The_Matching_Token() [Fact] public async Task Rejects_A_Wrong_Token() { - var wrongClient = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri($"localhost:{_fixture.Port}", connectionToken: "wrong") }); + var wrongClient = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri($"localhost:{_fixture.Port}", connectionToken: "wrong") }); try { @@ -76,7 +76,7 @@ public async Task Rejects_A_Wrong_Token() [Fact] public async Task Rejects_A_Missing_Token_When_One_Is_Required() { - var noTokenClient = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri($"localhost:{_fixture.Port}") }); + var noTokenClient = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri($"localhost:{_fixture.Port}") }); try { diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs index 8a13c4ac9..4e1ea2ddc 100644 --- a/dotnet/test/E2E/ClientE2ETests.cs +++ b/dotnet/test/E2E/ClientE2ETests.cs @@ -16,7 +16,7 @@ public class ClientE2ETests [InlineData(false)] // TCP transport public async Task Should_Start_And_Connect_To_Server(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); try { @@ -38,7 +38,7 @@ public async Task Should_Start_And_Connect_To_Server(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_Force_Stop_Without_Cleanup(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll }); await client.ForceStopAsync(); @@ -49,7 +49,7 @@ public async Task Should_Force_Stop_Without_Cleanup(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_Get_Status_With_Version_And_Protocol_Info(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); try { @@ -73,7 +73,7 @@ public async Task Should_Get_Status_With_Version_And_Protocol_Info(bool useStdio [InlineData(false)] // TCP transport public async Task Should_Get_Auth_Status(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); try { @@ -100,7 +100,7 @@ public async Task Should_Get_Auth_Status(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_List_Models_When_Authenticated(bool useStdio) { - using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); try { @@ -138,7 +138,7 @@ public async Task Should_List_Models_When_Authenticated(bool useStdio) [InlineData(false)] // TCP transport public async Task Should_Not_Throw_When_Disposing_Session_After_Stopping_Client(bool useStdio) { - await using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); await using var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll }); await client.StopAsync(); @@ -152,8 +152,8 @@ public async Task Should_Report_Error_With_Stderr_When_CLI_Fails_To_Start(bool u var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio - ? RuntimeConnection.Stdio(args: ["--nonexistent-flag-for-testing"]) - : RuntimeConnection.Tcp(args: ["--nonexistent-flag-for-testing"]) + ? RuntimeConnection.ForStdio(args: ["--nonexistent-flag-for-testing"]) + : RuntimeConnection.ForTcp(args: ["--nonexistent-flag-for-testing"]) }); var ex = await Assert.ThrowsAsync(() => client.StartAsync()); @@ -180,7 +180,7 @@ public async Task Should_Report_Error_With_Stderr_When_CLI_Fails_To_Start(bool u [InlineData(false)] // TCP transport public async Task Should_Allow_CreateSession_Called_Without_PermissionHandler(bool useStdio) { - await using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp() }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp() }); await using var session = await client.CreateSessionAsync(new SessionConfig()); Assert.NotNull(session.SessionId); @@ -194,7 +194,7 @@ public async Task Should_Allow_ResumeSession_Called_Without_PermissionHandler() await using var ctx = await E2ETestContext.CreateAsync(); await using var client = ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(connectionToken: connectionToken), + Connection = RuntimeConnection.ForTcp(connectionToken: connectionToken), }); await using var originalSession = await client.CreateSessionAsync(new SessionConfig()); @@ -203,7 +203,7 @@ public async Task Should_Allow_ResumeSession_Called_Without_PermissionHandler() await using var resumeClient = ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: connectionToken), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: connectionToken), }); await using var resumedSession = await resumeClient.ResumeSessionAsync(originalSession.SessionId, new()); @@ -232,7 +232,7 @@ public async Task ListModels_WithCustomHandler_CallsHandler(bool useStdio) var callCount = 0; await using var client = new CopilotClient(new CopilotClientOptions { - Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp(), + Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp(), OnListModels = (ct) => { callCount++; @@ -269,7 +269,7 @@ public async Task ListModels_WithCustomHandler_CachesResults(bool useStdio) var callCount = 0; await using var client = new CopilotClient(new CopilotClientOptions { - Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp(), + Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp(), OnListModels = (ct) => { callCount++; @@ -305,7 +305,7 @@ public async Task ListModels_WithCustomHandler_WorksWithoutStart(bool useStdio) var callCount = 0; await using var client = new CopilotClient(new CopilotClientOptions { - Connection = useStdio ? RuntimeConnection.Stdio() : RuntimeConnection.Tcp(), + Connection = useStdio ? RuntimeConnection.ForStdio() : RuntimeConnection.ForTcp(), OnListModels = (ct) => { callCount++; diff --git a/dotnet/test/E2E/ClientOptionsE2ETests.cs b/dotnet/test/E2E/ClientOptionsE2ETests.cs index a3644a955..142f46abb 100644 --- a/dotnet/test/E2E/ClientOptionsE2ETests.cs +++ b/dotnet/test/E2E/ClientOptionsE2ETests.cs @@ -20,7 +20,7 @@ public async Task Should_Listen_On_Configured_Tcp_Port() { var port = GetAvailableTcpPort(); await using var client = Ctx.CreateClient( - options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(port: port) }); + options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(port: port) }); await client.StartAsync(); Assert.Equal(port, client.RuntimePort); @@ -69,7 +69,7 @@ public async Task Should_Propagate_Process_Options_To_Spawned_Cli() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), + Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]), BaseDirectory = copilotHomeFromOption, Environment = clientEnv, GitHubToken = "process-option-token", @@ -131,7 +131,7 @@ public async Task Should_Forward_EnableSessionTelemetry_In_Wire_Request() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), + Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -158,7 +158,7 @@ public async Task Should_Omit_EnableSessionTelemetry_When_Not_Set() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), + Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -184,7 +184,7 @@ public async Task Should_Propagate_Activity_TraceContext_To_Session_Create_And_S await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), + Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -228,7 +228,7 @@ public async Task ForceStop_Does_Not_Rethrow_When_Tcp_Cli_Drops_During_Startup() await using var client = Ctx.CreateClient( options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(path: cliPath), + Connection = RuntimeConnection.ForTcp(path: cliPath), UseLoggedInUser = false, }); @@ -249,7 +249,7 @@ public async Task StartAsync_Cleans_Up_Tcp_Cli_Process_When_Connect_Fails() await using var client = Ctx.CreateClient( options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(path: cliPath, args: ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)]), + Connection = RuntimeConnection.ForTcp(path: cliPath, args: ["--pid-file", pidPath, "--announce-port", unavailablePort.ToString(CultureInfo.InvariantCulture)]), UseLoggedInUser = false, }); @@ -268,7 +268,7 @@ public async Task Should_Propagate_Activity_TraceContext_To_Session_Resume() await using var client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath, args: ["--capture-file", capturePath]), + Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]), UseLoggedInUser = false, }); @@ -340,7 +340,7 @@ public void Should_Throw_When_GitHubToken_Used_With_UriConnection() { Assert.Throws(() => { - _ = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri("localhost:8080"), GitHubToken = "gho_test_token" }); + _ = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri("localhost:8080"), GitHubToken = "gho_test_token" }); }); } @@ -349,7 +349,7 @@ public void Should_Throw_When_UseLoggedInUser_Used_With_UriConnection() { Assert.Throws(() => { - _ = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri("localhost:8080"), UseLoggedInUser = false }); + _ = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri("localhost:8080"), UseLoggedInUser = false }); }); } diff --git a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs index 559cfa6e3..d60c21709 100644 --- a/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs +++ b/dotnet/test/E2E/MultiClientCommandsElicitationE2ETests.cs @@ -24,7 +24,7 @@ public async Task InitializeAsync() Ctx = await E2ETestContext.CreateAsync(); Client1 = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(connectionToken: SharedToken), + Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken), }, persistent: true); } @@ -70,7 +70,7 @@ public async Task InitializeAsync() _client2 = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientCommandsElicitationFixture.SharedToken), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: MultiClientCommandsElicitationFixture.SharedToken), }); } @@ -218,7 +218,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec ?? throw new InvalidOperationException("Client1 RuntimePort is null"); _client3 = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientCommandsElicitationFixture.SharedToken), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: MultiClientCommandsElicitationFixture.SharedToken), }); // Client3 joins WITH elicitation handler diff --git a/dotnet/test/E2E/MultiClientE2ETests.cs b/dotnet/test/E2E/MultiClientE2ETests.cs index 981b812ea..34efd09b2 100644 --- a/dotnet/test/E2E/MultiClientE2ETests.cs +++ b/dotnet/test/E2E/MultiClientE2ETests.cs @@ -26,7 +26,7 @@ public async Task InitializeAsync() Ctx = await E2ETestContext.CreateAsync(); Client1 = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(connectionToken: SharedToken), + Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken), }, persistent: true); } @@ -68,7 +68,7 @@ public async Task InitializeAsync() _client2 = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientTestFixture.SharedToken), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: MultiClientTestFixture.SharedToken), }); } @@ -333,7 +333,7 @@ public async Task Disconnecting_Client_Removes_Its_Tools() var port = Client1.RuntimePort!.Value; _client2 = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: MultiClientTestFixture.SharedToken), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: MultiClientTestFixture.SharedToken), }); // Now only stable_tool should be available diff --git a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs index 50f8778aa..889dc0050 100644 --- a/dotnet/test/E2E/PendingWorkResumeE2ETests.cs +++ b/dotnet/test/E2E/PendingWorkResumeE2ETests.cs @@ -24,11 +24,11 @@ public async Task Should_Continue_Pending_Permission_Request_After_Resume() var releaseOriginalPermission = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var resumedToolInvoked = false; - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(ResumePermissionTool, "resume_permission_tool")], @@ -55,7 +55,7 @@ await session1.SendAsync(new MessageOptions await suspendedClient.ForceStopAsync(); - await using var resumedTcpClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + await using var resumedTcpClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedTcpClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -107,11 +107,11 @@ public async Task Should_Continue_Pending_External_Tool_Request_After_Resume() var originalToolStarted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var releaseOriginalTool = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(BlockingExternalTool, "resume_external_tool")], @@ -132,7 +132,7 @@ await session1.SendAsync(new MessageOptions Assert.Equal("beta", await originalToolStarted.Task.WaitAsync(PendingWorkTimeout)); await suspendedClient.ForceStopAsync(); - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -171,11 +171,11 @@ public async Task Should_Keep_Pending_External_Tool_Handleable_On_Warm_Resume_Wh var releaseOriginalTool = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var invocationCount = 0; - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(BlockingExternalTool, "resume_external_tool")], @@ -197,7 +197,7 @@ await session1.SendAsync(new MessageOptions await suspendedClient.ForceStopAsync(); - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = false, @@ -242,11 +242,11 @@ public async Task Should_Continue_Parallel_Pending_External_Tool_Requests_After_ var releaseOriginalToolA = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var releaseOriginalToolB = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); - using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + using var suspendedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session1 = await suspendedClient.CreateSessionAsync(new SessionConfig { Tools = @@ -276,7 +276,7 @@ await Task.WhenAll( await suspendedClient.ForceStopAsync(); - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var session2 = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -321,12 +321,12 @@ async Task BlockingToolB([Description("Value to look up")] string value) [Fact] public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() { - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); string sessionId; - await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) })) + await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) })) { var firstSession = await firstClient.CreateSessionAsync(new SessionConfig { @@ -340,7 +340,7 @@ public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() await firstSession.DisposeAsync(); } - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var resumedSession = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, @@ -359,12 +359,12 @@ public async Task Should_Resume_Successfully_When_No_Pending_Work_Exists() [Fact] public async Task Should_Report_ContinuePendingWork_True_In_Resume_Event() { - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: SharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: SharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); string sessionId; - await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) })) + await using (var firstClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) })) { var firstSession = await firstClient.CreateSessionAsync(new SessionConfig { @@ -381,7 +381,7 @@ public async Task Should_Report_ContinuePendingWork_True_In_Resume_Event() await firstSession.DisposeAsync(); } - await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: SharedToken) }); + await using var resumedClient = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: SharedToken) }); var resumedSession = await resumedClient.ResumeSessionAsync(sessionId, new ResumeSessionConfig { ContinuePendingWork = true, diff --git a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs index c202571c1..1219b14a4 100644 --- a/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs +++ b/dotnet/test/E2E/RpcExtensionsLoadedE2ETests.cs @@ -57,7 +57,7 @@ private CopilotClient CreateExtensionsClient() { return Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(args: ["--yolo"]), + Connection = RuntimeConnection.ForStdio(args: ["--yolo"]), Environment = ExtensionsEnabledEnvironment(), }); } diff --git a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs index 1ac013301..a3d08a1cb 100644 --- a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs +++ b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs @@ -102,7 +102,7 @@ public async Task Should_List_Extensions() // preventing breakage from new gates (e.g., extension-permission-access). await using var yoloClient = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(args: ["--yolo"]), + Connection = RuntimeConnection.ForStdio(args: ["--yolo"]), }); await using var session = await yoloClient.CreateSessionAsync(new SessionConfig { @@ -188,7 +188,7 @@ public async Task Should_Report_Error_When_Extensions_Are_Not_Available() // preventing breakage from new gates (e.g., extension-permission-access). await using var yoloClient = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(args: ["--yolo"]), + Connection = RuntimeConnection.ForStdio(args: ["--yolo"]), }); await using var session = await yoloClient.CreateSessionAsync(new SessionConfig { diff --git a/dotnet/test/E2E/SessionFsE2ETests.cs b/dotnet/test/E2E/SessionFsE2ETests.cs index f0b22b1c6..812fc8997 100644 --- a/dotnet/test/E2E/SessionFsE2ETests.cs +++ b/dotnet/test/E2E/SessionFsE2ETests.cs @@ -111,7 +111,7 @@ public async Task Should_Reject_SetProvider_When_Sessions_Already_Exist() { LogLevel = CopilotLogLevel.Error, SessionFs = SessionFsConfig, - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: "session-fs-shared-token"), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: "session-fs-shared-token"), }); try @@ -456,8 +456,8 @@ public async Task Should_Persist_Plan_Md_Via_SessionFs() private CopilotClient CreateSessionFsClient(string providerRoot, bool useStdio = true, string? tcpConnectionToken = null) { RuntimeConnection connection = useStdio - ? RuntimeConnection.Stdio() - : RuntimeConnection.Tcp(connectionToken: tcpConnectionToken); + ? RuntimeConnection.ForStdio() + : RuntimeConnection.ForTcp(connectionToken: tcpConnectionToken); Directory.CreateDirectory(providerRoot); return Ctx.CreateClient( diff --git a/dotnet/test/E2E/SuspendE2ETests.cs b/dotnet/test/E2E/SuspendE2ETests.cs index 8eb61da08..d3aa8067d 100644 --- a/dotnet/test/E2E/SuspendE2ETests.cs +++ b/dotnet/test/E2E/SuspendE2ETests.cs @@ -50,12 +50,12 @@ public async Task Should_Suspend_Idle_Session_Without_Throwing() public async Task Should_Allow_Resume_And_Continue_Conversation_After_Suspend() { const string sharedToken = "suspend-shared-token"; - await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Tcp(connectionToken: sharedToken) }); + await using var server = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForTcp(connectionToken: sharedToken) }); await server.StartAsync(); var cliUrl = GetCliUrl(server); string sessionId; - await using (var client1 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: sharedToken) })) + await using (var client1 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: sharedToken) })) { var session1 = await client1.CreateSessionAsync(new SessionConfig { @@ -76,7 +76,7 @@ await session1.SendAndWaitAsync(new MessageOptions // A different client should be able to pick the session back up. The previous // turn was completed before suspend, so there is no pending work to continue. - await using var client2 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl, connectionToken: sharedToken) }); + await using var client2 = Ctx.CreateClient(options: new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl, connectionToken: sharedToken) }); var session2 = await client2.ResumeSessionAsync(sessionId, new ResumeSessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, diff --git a/dotnet/test/Harness/E2ETestBase.cs b/dotnet/test/Harness/E2ETestBase.cs index 28cdd7f3d..592253bda 100644 --- a/dotnet/test/Harness/E2ETestBase.cs +++ b/dotnet/test/Harness/E2ETestBase.cs @@ -93,7 +93,7 @@ protected async Task ResumeSessionAsync(string sessionId, Resume var client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Uri($"localhost:{port}", connectionToken: E2ETestFixture.SharedTcpConnectionToken), + Connection = RuntimeConnection.ForUri($"localhost:{port}", connectionToken: E2ETestFixture.SharedTcpConnectionToken), }); return await client.ResumeSessionAsync(sessionId, config); } diff --git a/dotnet/test/Harness/E2ETestFixture.cs b/dotnet/test/Harness/E2ETestFixture.cs index 12f997073..95bebc139 100644 --- a/dotnet/test/Harness/E2ETestFixture.cs +++ b/dotnet/test/Harness/E2ETestFixture.cs @@ -19,7 +19,7 @@ public async Task InitializeAsync() Ctx = await E2ETestContext.CreateAsync(); Client = Ctx.CreateClient(options: new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(connectionToken: SharedTcpConnectionToken), + Connection = RuntimeConnection.ForTcp(connectionToken: SharedTcpConnectionToken), }, persistent: true); } diff --git a/dotnet/test/Unit/ClientSessionLifetimeTests.cs b/dotnet/test/Unit/ClientSessionLifetimeTests.cs index 239bda9da..5bd3335a5 100644 --- a/dotnet/test/Unit/ClientSessionLifetimeTests.cs +++ b/dotnet/test/Unit/ClientSessionLifetimeTests.cs @@ -19,7 +19,7 @@ public sealed class ClientSessionLifetimeTests public async Task Dropped_Session_Remains_Rooted_By_Client() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); var weakSession = await CreateDroppedSessionAsync(client); @@ -36,7 +36,7 @@ public async Task Dropped_Session_Remains_Rooted_By_Client() public async Task Disposed_Session_Is_Removed_From_Client() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); var session = await client.CreateSessionAsync(new SessionConfig { @@ -54,7 +54,7 @@ public async Task Disposing_Session_Remains_Rooted_Until_Destroy_Completes() { await using var server = await FakeCopilotServer.StartAsync(); server.DelayDestroy(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); var session = await client.CreateSessionAsync(new SessionConfig { @@ -77,7 +77,7 @@ public async Task Disposing_Session_Remains_Rooted_Until_Destroy_Completes() public async Task StopAsync_Removes_Rooted_Sessions() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); _ = await client.CreateSessionAsync(new SessionConfig { @@ -95,7 +95,7 @@ public async Task StopAsync_Keeps_Session_Rooted_Until_Destroy_Completes() { await using var server = await FakeCopilotServer.StartAsync(); server.DelayDestroy(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); _ = await client.CreateSessionAsync(new SessionConfig { @@ -118,7 +118,7 @@ public async Task StopAsync_Keeps_Session_Rooted_Until_Destroy_Completes() public async Task ResumeSessionAsync_Throws_When_Same_Client_Already_Tracks_Session() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); var sessionId = "same-session-id"; await using var session = await client.CreateSessionAsync(new SessionConfig @@ -140,7 +140,7 @@ public async Task ResumeSessionAsync_Throws_When_Same_Client_Already_Tracks_Sess public async Task Generated_Session_Rpc_Throws_When_Session_Disposed() { await using var server = await FakeCopilotServer.StartAsync(); - await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(server.Url) }); + await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) }); var session = await client.CreateSessionAsync(new SessionConfig { diff --git a/dotnet/test/Unit/CloneTests.cs b/dotnet/test/Unit/CloneTests.cs index 3dd25ab3e..184c13b18 100644 --- a/dotnet/test/Unit/CloneTests.cs +++ b/dotnet/test/Unit/CloneTests.cs @@ -13,7 +13,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() { var original = new CopilotClientOptions { - Connection = RuntimeConnection.Tcp(port: 8080, connectionToken: "tok", path: "/usr/bin/copilot", args: ["--verbose", "--debug"]), + Connection = RuntimeConnection.ForTcp(port: 8080, connectionToken: "tok", path: "/usr/bin/copilot", args: ["--verbose", "--debug"]), WorkingDirectory = "/home/user", LogLevel = CopilotLogLevel.Debug, Environment = new Dictionary { ["KEY"] = "value" }, @@ -40,7 +40,7 @@ public void CopilotClientOptions_Clone_CopiesAllProperties() [Fact] public void CopilotClientOptions_Clone_ConnectionIsShared() { - var connection = RuntimeConnection.Stdio(); + var connection = RuntimeConnection.ForStdio(); var original = new CopilotClientOptions { Connection = connection }; var clone = original.Clone(); diff --git a/test/scenarios/auth/byok-anthropic/csharp/Program.cs b/test/scenarios/auth/byok-anthropic/csharp/Program.cs index d55ee8f87..f29cfd4d8 100644 --- a/test/scenarios/auth/byok-anthropic/csharp/Program.cs +++ b/test/scenarios/auth/byok-anthropic/csharp/Program.cs @@ -12,7 +12,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/byok-azure/csharp/Program.cs b/test/scenarios/auth/byok-azure/csharp/Program.cs index c51d48e05..64132bbff 100644 --- a/test/scenarios/auth/byok-azure/csharp/Program.cs +++ b/test/scenarios/auth/byok-azure/csharp/Program.cs @@ -13,7 +13,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/byok-ollama/csharp/Program.cs b/test/scenarios/auth/byok-ollama/csharp/Program.cs index 286f78754..69578a378 100644 --- a/test/scenarios/auth/byok-ollama/csharp/Program.cs +++ b/test/scenarios/auth/byok-ollama/csharp/Program.cs @@ -8,7 +8,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/byok-openai/csharp/Program.cs b/test/scenarios/auth/byok-openai/csharp/Program.cs index d95a972e7..d98cffbc3 100644 --- a/test/scenarios/auth/byok-openai/csharp/Program.cs +++ b/test/scenarios/auth/byok-openai/csharp/Program.cs @@ -12,7 +12,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), }); await client.StartAsync(); diff --git a/test/scenarios/auth/gh-app/csharp/Program.cs b/test/scenarios/auth/gh-app/csharp/Program.cs index 7dcbccd11..5933ec087 100644 --- a/test/scenarios/auth/gh-app/csharp/Program.cs +++ b/test/scenarios/auth/gh-app/csharp/Program.cs @@ -60,7 +60,7 @@ // Step 4: Use the token with Copilot using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = accessToken, }); diff --git a/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs b/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs index 67b106ea8..f6e993f0c 100644 --- a/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs +++ b/test/scenarios/bundling/app-backend-to-server/csharp/Program.cs @@ -21,7 +21,7 @@ return; } - using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); + using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/bundling/app-direct-server/csharp/Program.cs b/test/scenarios/bundling/app-direct-server/csharp/Program.cs index e6e3561a3..c7b9fec70 100644 --- a/test/scenarios/bundling/app-direct-server/csharp/Program.cs +++ b/test/scenarios/bundling/app-direct-server/csharp/Program.cs @@ -2,7 +2,7 @@ var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; -using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); +using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/bundling/container-proxy/csharp/Program.cs b/test/scenarios/bundling/container-proxy/csharp/Program.cs index e6e3561a3..c7b9fec70 100644 --- a/test/scenarios/bundling/container-proxy/csharp/Program.cs +++ b/test/scenarios/bundling/container-proxy/csharp/Program.cs @@ -2,7 +2,7 @@ var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; -using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); +using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/bundling/fully-bundled/csharp/Program.cs b/test/scenarios/bundling/fully-bundled/csharp/Program.cs index df042773f..e9dfbcccc 100644 --- a/test/scenarios/bundling/fully-bundled/csharp/Program.cs +++ b/test/scenarios/bundling/fully-bundled/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/callbacks/hooks/csharp/Program.cs b/test/scenarios/callbacks/hooks/csharp/Program.cs index e8ae5bd95..78184df2a 100644 --- a/test/scenarios/callbacks/hooks/csharp/Program.cs +++ b/test/scenarios/callbacks/hooks/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/callbacks/permissions/csharp/Program.cs b/test/scenarios/callbacks/permissions/csharp/Program.cs index 93dbe3508..cf3275e56 100644 --- a/test/scenarios/callbacks/permissions/csharp/Program.cs +++ b/test/scenarios/callbacks/permissions/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/callbacks/user-input/csharp/Program.cs b/test/scenarios/callbacks/user-input/csharp/Program.cs index 73c4c8845..e9fe06968 100644 --- a/test/scenarios/callbacks/user-input/csharp/Program.cs +++ b/test/scenarios/callbacks/user-input/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/modes/default/csharp/Program.cs b/test/scenarios/modes/default/csharp/Program.cs index f868b1f13..23d6c63f0 100644 --- a/test/scenarios/modes/default/csharp/Program.cs +++ b/test/scenarios/modes/default/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/modes/minimal/csharp/Program.cs b/test/scenarios/modes/minimal/csharp/Program.cs index 15aac333a..70081b58d 100644 --- a/test/scenarios/modes/minimal/csharp/Program.cs +++ b/test/scenarios/modes/minimal/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/prompts/attachments/csharp/Program.cs b/test/scenarios/prompts/attachments/csharp/Program.cs index 4f4974877..7cafcb86d 100644 --- a/test/scenarios/prompts/attachments/csharp/Program.cs +++ b/test/scenarios/prompts/attachments/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/prompts/reasoning-effort/csharp/Program.cs b/test/scenarios/prompts/reasoning-effort/csharp/Program.cs index 186b843aa..2ed2ae94d 100644 --- a/test/scenarios/prompts/reasoning-effort/csharp/Program.cs +++ b/test/scenarios/prompts/reasoning-effort/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/prompts/system-message/csharp/Program.cs b/test/scenarios/prompts/system-message/csharp/Program.cs index e211e678b..48afdd7ba 100644 --- a/test/scenarios/prompts/system-message/csharp/Program.cs +++ b/test/scenarios/prompts/system-message/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs b/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs index 8dfa75a3d..a5ba2577b 100644 --- a/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs +++ b/test/scenarios/sessions/concurrent-sessions/csharp/Program.cs @@ -5,7 +5,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/infinite-sessions/csharp/Program.cs b/test/scenarios/sessions/infinite-sessions/csharp/Program.cs index b3c6169c1..2619f25b4 100644 --- a/test/scenarios/sessions/infinite-sessions/csharp/Program.cs +++ b/test/scenarios/sessions/infinite-sessions/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/session-resume/csharp/Program.cs b/test/scenarios/sessions/session-resume/csharp/Program.cs index c5a8f93ef..a1bd015bd 100644 --- a/test/scenarios/sessions/session-resume/csharp/Program.cs +++ b/test/scenarios/sessions/session-resume/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/sessions/streaming/csharp/Program.cs b/test/scenarios/sessions/streaming/csharp/Program.cs index a2445e22b..518d4b227 100644 --- a/test/scenarios/sessions/streaming/csharp/Program.cs +++ b/test/scenarios/sessions/streaming/csharp/Program.cs @@ -8,7 +8,7 @@ var cliPath = Environment.GetEnvironmentVariable("COPILOT_CLI_PATH"); if (!string.IsNullOrEmpty(cliPath)) { - options.Connection = RuntimeConnection.Stdio(path: cliPath); + options.Connection = RuntimeConnection.ForStdio(path: cliPath); } using var client = new CopilotClient(options); diff --git a/test/scenarios/tools/custom-agents/csharp/Program.cs b/test/scenarios/tools/custom-agents/csharp/Program.cs index ecf1a12fe..6c5b980cc 100644 --- a/test/scenarios/tools/custom-agents/csharp/Program.cs +++ b/test/scenarios/tools/custom-agents/csharp/Program.cs @@ -5,7 +5,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: cliPath), + Connection = RuntimeConnection.ForStdio(path: cliPath), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/mcp-servers/csharp/Program.cs b/test/scenarios/tools/mcp-servers/csharp/Program.cs index 6aea8fdab..ed667825f 100644 --- a/test/scenarios/tools/mcp-servers/csharp/Program.cs +++ b/test/scenarios/tools/mcp-servers/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/no-tools/csharp/Program.cs b/test/scenarios/tools/no-tools/csharp/Program.cs index 4e383a239..a0ea0eefe 100644 --- a/test/scenarios/tools/no-tools/csharp/Program.cs +++ b/test/scenarios/tools/no-tools/csharp/Program.cs @@ -9,7 +9,7 @@ You can only respond with text based on your training data. using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/skills/csharp/Program.cs b/test/scenarios/tools/skills/csharp/Program.cs index 784d9ef50..81adf96a5 100644 --- a/test/scenarios/tools/skills/csharp/Program.cs +++ b/test/scenarios/tools/skills/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/tool-filtering/csharp/Program.cs b/test/scenarios/tools/tool-filtering/csharp/Program.cs index 66c663166..72431c005 100644 --- a/test/scenarios/tools/tool-filtering/csharp/Program.cs +++ b/test/scenarios/tools/tool-filtering/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/tool-overrides/csharp/Program.cs b/test/scenarios/tools/tool-overrides/csharp/Program.cs index d02cf5bd6..a8c7679de 100644 --- a/test/scenarios/tools/tool-overrides/csharp/Program.cs +++ b/test/scenarios/tools/tool-overrides/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/tools/virtual-filesystem/csharp/Program.cs b/test/scenarios/tools/virtual-filesystem/csharp/Program.cs index f758eb92f..93ad41f1e 100644 --- a/test/scenarios/tools/virtual-filesystem/csharp/Program.cs +++ b/test/scenarios/tools/virtual-filesystem/csharp/Program.cs @@ -7,7 +7,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/transport/reconnect/csharp/Program.cs b/test/scenarios/transport/reconnect/csharp/Program.cs index bbc0022b3..99e9b91dd 100644 --- a/test/scenarios/transport/reconnect/csharp/Program.cs +++ b/test/scenarios/transport/reconnect/csharp/Program.cs @@ -2,7 +2,7 @@ var cliUrl = Environment.GetEnvironmentVariable("COPILOT_CLI_URL") ?? "localhost:3000"; -using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.Uri(cliUrl) }); +using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(cliUrl) }); await client.StartAsync(); try diff --git a/test/scenarios/transport/stdio/csharp/Program.cs b/test/scenarios/transport/stdio/csharp/Program.cs index df042773f..e9dfbcccc 100644 --- a/test/scenarios/transport/stdio/csharp/Program.cs +++ b/test/scenarios/transport/stdio/csharp/Program.cs @@ -2,7 +2,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Stdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), + Connection = RuntimeConnection.ForStdio(path: Environment.GetEnvironmentVariable("COPILOT_CLI_PATH")), GitHubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN"), }); diff --git a/test/scenarios/transport/tcp/csharp/Program.cs b/test/scenarios/transport/tcp/csharp/Program.cs index 4cd007a8f..9fe2b176b 100644 --- a/test/scenarios/transport/tcp/csharp/Program.cs +++ b/test/scenarios/transport/tcp/csharp/Program.cs @@ -4,7 +4,7 @@ using var client = new CopilotClient(new CopilotClientOptions { - Connection = RuntimeConnection.Uri(cliUrl), + Connection = RuntimeConnection.ForUri(cliUrl), }); await client.StartAsync(); From 26eedfd77b39744a2b33d6cbdefa20b4576700d8 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 21 May 2026 09:52:06 +0100 Subject: [PATCH 35/40] Apply RuntimeConnection.For* rename in E2ETestContext.cs Missed in 5e412804; this file was excluded from the original add because of an earlier uncommitted debug hunk that has since been committed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/Harness/E2ETestContext.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index 1c4eb6125..1819eb634 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -228,7 +228,7 @@ public CopilotClient CreateClient( { throw new ArgumentException( "Specify either useStdio or options.Connection, not both. " + - "Use options.Connection (e.g. RuntimeConnection.Stdio() / RuntimeConnection.Tcp()) to control transport when supplying a Connection.", + "Use options.Connection (e.g. RuntimeConnection.ForStdio() / RuntimeConnection.ForTcp()) to control transport when supplying a Connection.", nameof(useStdio)); } @@ -237,8 +237,8 @@ public CopilotClient CreateClient( { case null: options.Connection = useStdio == false - ? RuntimeConnection.Tcp(path: cliPath) - : RuntimeConnection.Stdio(path: cliPath); + ? RuntimeConnection.ForTcp(path: cliPath) + : RuntimeConnection.ForStdio(path: cliPath); break; case ChildProcessRuntimeConnection child when child.Path is null: child.Path = cliPath; From db9e0ed6f393145aef716281a3407d472256e51c Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 21 May 2026 09:52:55 +0100 Subject: [PATCH 36/40] Docs: restore 'dotnet add package GitHub.Copilot.SDK' The package name is not changing; only the C# namespace lost the .SDK suffix. My earlier bulk rename incorrectly stripped .SDK from these three docs install commands too. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/getting-started.md | 2 +- docs/integrations/microsoft-agent-framework.md | 2 +- docs/setup/choosing-a-setup-path.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index b5d7caa21..3a43fad7c 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -109,7 +109,7 @@ dotnet new console -n CopilotDemo && cd CopilotDemo Then add the SDK: ```bash -dotnet add package GitHub.Copilot +dotnet add package GitHub.Copilot.SDK ``` diff --git a/docs/integrations/microsoft-agent-framework.md b/docs/integrations/microsoft-agent-framework.md index 9480bcbcf..1802ddd4b 100644 --- a/docs/integrations/microsoft-agent-framework.md +++ b/docs/integrations/microsoft-agent-framework.md @@ -32,7 +32,7 @@ Install the Copilot SDK alongside the MAF integration package for your language: .NET ```shell -dotnet add package GitHub.Copilot +dotnet add package GitHub.Copilot.SDK dotnet add package Microsoft.Agents.AI.GitHub.Copilot --prerelease ``` diff --git a/docs/setup/choosing-a-setup-path.md b/docs/setup/choosing-a-setup-path.md index 2fa27606a..f1c4636c6 100644 --- a/docs/setup/choosing-a-setup-path.md +++ b/docs/setup/choosing-a-setup-path.md @@ -133,7 +133,7 @@ All guides assume you have: * Node.js: `npm install @github/copilot-sdk` * Python: `pip install github-copilot-sdk` * Go: `go get github.com/github/copilot-sdk/go` (requires separate CLI installation) - * .NET: `dotnet add package GitHub.Copilot` + * .NET: `dotnet add package GitHub.Copilot.SDK` If you're brand new, start with the **[Getting Started tutorial](../getting-started.md)** first, then come back here for production configuration. From f7d86460dd4d69435f946efa7e6ae21821431557 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 21 May 2026 09:54:23 +0100 Subject: [PATCH 37/40] Dev version --- dotnet/src/GitHub.Copilot.SDK.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/GitHub.Copilot.SDK.csproj b/dotnet/src/GitHub.Copilot.SDK.csproj index 7fa03ff4a..2b69cbb6f 100644 --- a/dotnet/src/GitHub.Copilot.SDK.csproj +++ b/dotnet/src/GitHub.Copilot.SDK.csproj @@ -4,7 +4,7 @@ net8.0;net10.0;netstandard2.0 GitHub.Copilot true - 0.1.0 + 0.0.0-dev SDK for programmatic control of GitHub Copilot CLI GitHub GitHub From 263dfc3ce2a7f8f9d2f404ebd9ca5bfca18b5664 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 21 May 2026 09:55:50 +0100 Subject: [PATCH 38/40] Codegen: drop full GitHub.Copilot qualifier from GeneratedStringEnumJson refs After the namespace rename, GeneratedStringEnumJson sits in the parent namespace of the generated converters (GitHub.Copilot.Rpc), so the unqualified name resolves correctly. Removes leftover qualifier that was needed to disambiguate against the old GitHub.Copilot.SDK namespace. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 176 +++++++++++++------------- dotnet/src/Generated/SessionEvents.cs | 112 ++++++++-------- scripts/codegen/csharp.ts | 4 +- 3 files changed, 146 insertions(+), 146 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index f1a7c0396..3f3a84738 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -6622,13 +6622,13 @@ public sealed class Converter : JsonConverter /// public override ModelPickerCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelPickerCategory value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerCategory)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerCategory)); } } } @@ -6690,13 +6690,13 @@ public sealed class Converter : JsonConverter /// public override ModelPickerPriceCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelPickerPriceCategory value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerPriceCategory)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerPriceCategory)); } } } @@ -6755,13 +6755,13 @@ public sealed class Converter : JsonConverter /// public override ModelPolicyState Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelPolicyState value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPolicyState)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPolicyState)); } } } @@ -6823,13 +6823,13 @@ public sealed class Converter : JsonConverter /// public override DiscoveredMcpServerType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, DiscoveredMcpServerType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(DiscoveredMcpServerType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(DiscoveredMcpServerType)); } } } @@ -6885,13 +6885,13 @@ public sealed class Converter : JsonConverter /// public override SessionFsSetProviderConventions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsSetProviderConventions value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSetProviderConventions)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSetProviderConventions)); } } } @@ -6948,13 +6948,13 @@ public sealed class Converter : JsonConverter public override ConnectedRemoteSessionMetadataKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ConnectedRemoteSessionMetadataKind value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ConnectedRemoteSessionMetadataKind)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ConnectedRemoteSessionMetadataKind)); } } } @@ -7011,13 +7011,13 @@ public sealed class Converter : JsonConverter /// public override SessionContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionContextHostType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionContextHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionContextHostType)); } } } @@ -7079,13 +7079,13 @@ public sealed class Converter : JsonConverter /// public override SendAgentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SendAgentMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAgentMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAgentMode)); } } } @@ -7144,13 +7144,13 @@ public sealed class Converter : JsonConverter /// public override SendAttachmentGithubReferenceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SendAttachmentGithubReferenceType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAttachmentGithubReferenceType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAttachmentGithubReferenceType)); } } } @@ -7206,13 +7206,13 @@ public sealed class Converter : JsonConverter /// public override SendMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SendMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendMode)); } } } @@ -7271,13 +7271,13 @@ public sealed class Converter : JsonConverter /// public override SessionLogLevel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionLogLevel value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionLogLevel)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionLogLevel)); } } } @@ -7348,13 +7348,13 @@ public sealed class Converter : JsonConverter /// public override AuthInfoType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AuthInfoType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AuthInfoType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AuthInfoType)); } } } @@ -7410,13 +7410,13 @@ public sealed class Converter : JsonConverter public override WorkspacesGetWorkspaceResultWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, WorkspacesGetWorkspaceResultWorkspaceHostType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); } } } @@ -7478,13 +7478,13 @@ public sealed class Converter : JsonConverter /// public override InstructionsSourcesLocation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, InstructionsSourcesLocation value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesLocation)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesLocation)); } } } @@ -7555,13 +7555,13 @@ public sealed class Converter : JsonConverter /// public override InstructionsSourcesType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, InstructionsSourcesType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesType)); } } } @@ -7630,13 +7630,13 @@ public sealed class Converter : JsonConverter /// public override AgentInfoSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AgentInfoSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AgentInfoSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AgentInfoSource)); } } } @@ -7693,13 +7693,13 @@ public sealed class Converter : JsonConverter /// public override TaskExecutionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, TaskExecutionMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskExecutionMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskExecutionMode)); } } } @@ -7765,13 +7765,13 @@ public sealed class Converter : JsonConverter /// public override TaskStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, TaskStatus value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskStatus)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskStatus)); } } } @@ -7828,13 +7828,13 @@ public sealed class Converter : JsonConverter /// public override TaskShellInfoAttachmentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, TaskShellInfoAttachmentMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskShellInfoAttachmentMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskShellInfoAttachmentMode)); } } } @@ -7894,13 +7894,13 @@ public sealed class Converter : JsonConverter /// public override McpSamplingExecutionAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpSamplingExecutionAction value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSamplingExecutionAction)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSamplingExecutionAction)); } } } @@ -7957,13 +7957,13 @@ public sealed class Converter : JsonConverter /// public override McpSetEnvValueModeDetails Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpSetEnvValueModeDetails value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSetEnvValueModeDetails)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSetEnvValueModeDetails)); } } } @@ -8020,13 +8020,13 @@ public sealed class Converter : JsonConverter /// public override OptionsUpdateEnvValueMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, OptionsUpdateEnvValueMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(OptionsUpdateEnvValueMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(OptionsUpdateEnvValueMode)); } } } @@ -8083,13 +8083,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionSource)); } } } @@ -8152,13 +8152,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionStatus value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionStatus)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionStatus)); } } } @@ -8211,13 +8211,13 @@ public sealed class Converter : JsonConverter /// public override SlashCommandInputCompletion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SlashCommandInputCompletion value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandInputCompletion)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandInputCompletion)); } } } @@ -8276,13 +8276,13 @@ public sealed class Converter : JsonConverter /// public override SlashCommandKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SlashCommandKind value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandKind)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandKind)); } } } @@ -8341,13 +8341,13 @@ public sealed class Converter : JsonConverter /// public override UIElicitationResponseAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UIElicitationResponseAction value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIElicitationResponseAction)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIElicitationResponseAction)); } } } @@ -8406,13 +8406,13 @@ public sealed class Converter : JsonConverter /// public override UIAutoModeSwitchResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UIAutoModeSwitchResponse value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIAutoModeSwitchResponse)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIAutoModeSwitchResponse)); } } } @@ -8474,13 +8474,13 @@ public sealed class Converter : JsonConverter /// public override UIExitPlanModeAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UIExitPlanModeAction value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIExitPlanModeAction)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIExitPlanModeAction)); } } } @@ -8536,13 +8536,13 @@ public sealed class Converter : JsonConverter public override PermissionsConfigureAdditionalContentExclusionPolicyScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionsConfigureAdditionalContentExclusionPolicyScope value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsConfigureAdditionalContentExclusionPolicyScope)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsConfigureAdditionalContentExclusionPolicyScope)); } } } @@ -8604,13 +8604,13 @@ public sealed class Converter : JsonConverter /// public override PermissionsSetApproveAllSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionsSetApproveAllSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsSetApproveAllSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsSetApproveAllSource)); } } } @@ -8666,13 +8666,13 @@ public sealed class Converter : JsonConverter /// public override PermissionsModifyRulesScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionsModifyRulesScope value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsModifyRulesScope)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsModifyRulesScope)); } } } @@ -8732,13 +8732,13 @@ public sealed class Converter : JsonConverter /// public override MetadataSnapshotCurrentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, MetadataSnapshotCurrentMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotCurrentMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotCurrentMode)); } } } @@ -8795,13 +8795,13 @@ public sealed class Converter : JsonConverter public override MetadataSnapshotRemoteMetadataTaskType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, MetadataSnapshotRemoteMetadataTaskType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotRemoteMetadataTaskType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotRemoteMetadataTaskType)); } } } @@ -8857,13 +8857,13 @@ public sealed class Converter : JsonConverter public override SessionMetadataSnapshotWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionMetadataSnapshotWorkspaceHostType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); } } } @@ -8920,13 +8920,13 @@ public sealed class Converter : JsonConverter public override SessionWorkingDirectoryContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionWorkingDirectoryContextHostType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionWorkingDirectoryContextHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionWorkingDirectoryContextHostType)); } } } @@ -8985,13 +8985,13 @@ public sealed class Converter : JsonConverter /// public override ShellKillSignal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ShellKillSignal value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShellKillSignal)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShellKillSignal)); } } } @@ -9048,13 +9048,13 @@ public sealed class Converter : JsonConverter /// public override QueuePendingItemsKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, QueuePendingItemsKind value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(QueuePendingItemsKind)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(QueuePendingItemsKind)); } } } @@ -9111,13 +9111,13 @@ public sealed class Converter : JsonConverter /// public override EventsCursorStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, EventsCursorStatus value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsCursorStatus)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsCursorStatus)); } } } @@ -9174,13 +9174,13 @@ public sealed class Converter : JsonConverter /// public override EventsAgentScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, EventsAgentScope value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsAgentScope)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsAgentScope)); } } } @@ -9240,13 +9240,13 @@ public sealed class Converter : JsonConverter /// public override RemoteSessionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, RemoteSessionMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(RemoteSessionMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(RemoteSessionMode)); } } } @@ -9302,13 +9302,13 @@ public sealed class Converter : JsonConverter /// public override SessionFsErrorCode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsErrorCode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsErrorCode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsErrorCode)); } } } @@ -9364,13 +9364,13 @@ public sealed class Converter : JsonConverter public override SessionFsReaddirWithTypesEntryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsReaddirWithTypesEntryType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsReaddirWithTypesEntryType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsReaddirWithTypesEntryType)); } } } @@ -9429,13 +9429,13 @@ public sealed class Converter : JsonConverter /// public override SessionFsSqliteQueryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionFsSqliteQueryType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSqliteQueryType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSqliteQueryType)); } } } diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index 7a8ccdb15..b0db5de05 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -5345,13 +5345,13 @@ public sealed class Converter : JsonConverter /// public override WorkingDirectoryContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, WorkingDirectoryContextHostType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkingDirectoryContextHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkingDirectoryContextHostType)); } } } @@ -5409,13 +5409,13 @@ public sealed class Converter : JsonConverter /// public override ReasoningSummary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ReasoningSummary value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ReasoningSummary)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ReasoningSummary)); } } } @@ -5473,13 +5473,13 @@ public sealed class Converter : JsonConverter /// public override SessionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SessionMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMode)); } } } @@ -5537,13 +5537,13 @@ public sealed class Converter : JsonConverter /// public override PlanChangedOperation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PlanChangedOperation value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PlanChangedOperation)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PlanChangedOperation)); } } } @@ -5598,13 +5598,13 @@ public sealed class Converter : JsonConverter /// public override WorkspaceFileChangedOperation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, WorkspaceFileChangedOperation value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspaceFileChangedOperation)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspaceFileChangedOperation)); } } } @@ -5659,13 +5659,13 @@ public sealed class Converter : JsonConverter /// public override HandoffSourceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, HandoffSourceType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(HandoffSourceType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(HandoffSourceType)); } } } @@ -5720,13 +5720,13 @@ public sealed class Converter : JsonConverter /// public override ShutdownType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ShutdownType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShutdownType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShutdownType)); } } } @@ -5787,13 +5787,13 @@ public sealed class Converter : JsonConverter /// public override UserMessageAgentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UserMessageAgentMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAgentMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAgentMode)); } } } @@ -5851,13 +5851,13 @@ public sealed class Converter : JsonConverter public override UserMessageAttachmentGithubReferenceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, UserMessageAttachmentGithubReferenceType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAttachmentGithubReferenceType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UserMessageAttachmentGithubReferenceType)); } } } @@ -5912,13 +5912,13 @@ public sealed class Converter : JsonConverter /// public override AssistantMessageToolRequestType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AssistantMessageToolRequestType value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantMessageToolRequestType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantMessageToolRequestType)); } } } @@ -5979,13 +5979,13 @@ public sealed class Converter : JsonConverter /// public override AssistantUsageApiEndpoint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AssistantUsageApiEndpoint value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantUsageApiEndpoint)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AssistantUsageApiEndpoint)); } } } @@ -6043,13 +6043,13 @@ public sealed class Converter : JsonConverter /// public override ModelCallFailureSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ModelCallFailureSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelCallFailureSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelCallFailureSource)); } } } @@ -6107,13 +6107,13 @@ public sealed class Converter : JsonConverter /// public override AbortReason Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AbortReason value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AbortReason)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AbortReason)); } } } @@ -6168,13 +6168,13 @@ public sealed class Converter : JsonConverter public override ToolExecutionCompleteContentResourceLinkIconTheme Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ToolExecutionCompleteContentResourceLinkIconTheme value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ToolExecutionCompleteContentResourceLinkIconTheme)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ToolExecutionCompleteContentResourceLinkIconTheme)); } } } @@ -6229,13 +6229,13 @@ public sealed class Converter : JsonConverter /// public override SystemMessageRole Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SystemMessageRole value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemMessageRole)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemMessageRole)); } } } @@ -6290,13 +6290,13 @@ public sealed class Converter : JsonConverter public override SystemNotificationAgentCompletedStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SystemNotificationAgentCompletedStatus value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemNotificationAgentCompletedStatus)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SystemNotificationAgentCompletedStatus)); } } } @@ -6351,13 +6351,13 @@ public sealed class Converter : JsonConverter /// public override PermissionRequestMemoryAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionRequestMemoryAction value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryAction)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryAction)); } } } @@ -6412,13 +6412,13 @@ public sealed class Converter : JsonConverter /// public override PermissionRequestMemoryDirection Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionRequestMemoryDirection value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryDirection)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionRequestMemoryDirection)); } } } @@ -6476,13 +6476,13 @@ public sealed class Converter : JsonConverter public override PermissionPromptRequestPathAccessKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, PermissionPromptRequestPathAccessKind value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionPromptRequestPathAccessKind)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionPromptRequestPathAccessKind)); } } } @@ -6537,13 +6537,13 @@ public sealed class Converter : JsonConverter /// public override ElicitationRequestedMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ElicitationRequestedMode value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationRequestedMode)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationRequestedMode)); } } } @@ -6601,13 +6601,13 @@ public sealed class Converter : JsonConverter /// public override ElicitationCompletedAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ElicitationCompletedAction value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationCompletedAction)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ElicitationCompletedAction)); } } } @@ -6665,13 +6665,13 @@ public sealed class Converter : JsonConverter /// public override AutoModeSwitchResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, AutoModeSwitchResponse value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AutoModeSwitchResponse)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AutoModeSwitchResponse)); } } } @@ -6732,13 +6732,13 @@ public sealed class Converter : JsonConverter /// public override ExitPlanModeAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExitPlanModeAction value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExitPlanModeAction)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExitPlanModeAction)); } } } @@ -6808,13 +6808,13 @@ public sealed class Converter : JsonConverter /// public override SkillSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, SkillSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SkillSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SkillSource)); } } } @@ -6875,13 +6875,13 @@ public sealed class Converter : JsonConverter /// public override McpServerSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpServerSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerSource)); } } } @@ -6948,13 +6948,13 @@ public sealed class Converter : JsonConverter /// public override McpServerStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, McpServerStatus value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerStatus)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpServerStatus)); } } } @@ -7009,13 +7009,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionsLoadedExtensionSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionsLoadedExtensionSource value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionSource)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionSource)); } } } @@ -7076,13 +7076,13 @@ public sealed class Converter : JsonConverter /// public override ExtensionsLoadedExtensionStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// public override void Write(Utf8JsonWriter writer, ExtensionsLoadedExtensionStatus value, JsonSerializerOptions options) { - GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionStatus)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionsLoadedExtensionStatus)); } } } diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index fa57a0e34..f35c0a52b 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -569,12 +569,12 @@ function getOrCreateEnum( lines.push(` /// `); lines.push(` public override ${enumName} Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)`); lines.push(` {`); - lines.push(` return new(GitHub.Copilot.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert));`); + lines.push(` return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert));`); lines.push(` }`, ""); lines.push(` /// `); lines.push(` public override void Write(Utf8JsonWriter writer, ${enumName} value, JsonSerializerOptions options)`); lines.push(` {`); - lines.push(` GitHub.Copilot.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(${enumName}));`); + lines.push(` GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(${enumName}));`); lines.push(` }`); lines.push(` }`); lines.push(`}`, ""); From 3e1a3e124d0fc849992a17cb08816c3980361e72 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 21 May 2026 09:59:38 +0100 Subject: [PATCH 39/40] Regenerate Rpc.cs after rebase onto origin/main Picks up @github/copilot 1.0.51 schema changes (#1351, #1353) and MCPStdioServerConfig.args optional (#1347). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 1263 ++++++++++++++++++++++++++++------- 1 file changed, 1031 insertions(+), 232 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 3f3a84738..db7ce9d4c 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -708,7 +708,8 @@ public sealed class SessionList } /// Optional filter applied to the returned sessions. -public sealed class SessionsListRequestFilter +[Experimental(Diagnostics.Experimental)] +public sealed class SessionListFilter { /// Match sessions whose context.branch equals this value. [JsonPropertyName("branch")] @@ -733,7 +734,7 @@ internal sealed class SessionsListRequest { /// Optional filter applied to the returned sessions. [JsonPropertyName("filter")] - public SessionsListRequestFilter? Filter { get; set; } + public SessionListFilter? Filter { get; set; } /// When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. [JsonPropertyName("metadataLimit")] @@ -1074,6 +1075,7 @@ internal sealed class SessionsSetAdditionalPluginsRequest } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionSuspendRequest { /// Target session identifier. @@ -1082,6 +1084,7 @@ internal sealed class SessionSuspendRequest } /// Result of sending a user message. +[Experimental(Diagnostics.Experimental)] public sealed class SendResult { /// Unique identifier assigned to the message. @@ -1091,6 +1094,7 @@ public sealed class SendResult /// A user message attachment — a file, directory, code selection, blob, or GitHub reference. /// Polymorphic base type discriminated by type. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -1108,6 +1112,7 @@ public partial class SendAttachment /// Optional line range to scope the attachment to a specific section of the file. +[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentFileLineRange { /// End line number (1-based, inclusive). @@ -1121,6 +1126,7 @@ public sealed class SendAttachmentFileLineRange /// File attachment. /// The file variant of . +[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentFile : SendAttachment { /// @@ -1143,6 +1149,7 @@ public partial class SendAttachmentFile : SendAttachment /// Directory attachment. /// The directory variant of . +[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentDirectory : SendAttachment { /// @@ -1159,6 +1166,7 @@ public partial class SendAttachmentDirectory : SendAttachment } /// End position of the selection. +[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentSelectionDetailsEnd { /// End character offset within the line (0-based). @@ -1171,6 +1179,7 @@ public sealed class SendAttachmentSelectionDetailsEnd } /// Start position of the selection. +[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentSelectionDetailsStart { /// Start character offset within the line (0-based). @@ -1183,6 +1192,7 @@ public sealed class SendAttachmentSelectionDetailsStart } /// Position range of the selection within the file. +[Experimental(Diagnostics.Experimental)] public sealed class SendAttachmentSelectionDetails { /// End position of the selection. @@ -1196,6 +1206,7 @@ public sealed class SendAttachmentSelectionDetails /// Code selection attachment from an editor. /// The selection variant of . +[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentSelection : SendAttachment { /// @@ -1221,6 +1232,7 @@ public partial class SendAttachmentSelection : SendAttachment /// GitHub issue, pull request, or discussion reference. /// The github_reference variant of . +[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentGithubReference : SendAttachment { /// @@ -1252,6 +1264,7 @@ public partial class SendAttachmentGithubReference : SendAttachment /// Blob attachment with inline base64-encoded data. /// The blob variant of . +[Experimental(Diagnostics.Experimental)] public partial class SendAttachmentBlob : SendAttachment { /// @@ -1274,6 +1287,7 @@ public partial class SendAttachmentBlob : SendAttachment } /// Parameters for sending a user message to the session. +[Experimental(Diagnostics.Experimental)] internal sealed class SendRequest { /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. @@ -1334,6 +1348,7 @@ internal sealed class SendRequest } /// Result of aborting the current turn. +[Experimental(Diagnostics.Experimental)] public sealed class AbortResult { /// Error message if the abort failed. @@ -1346,6 +1361,7 @@ public sealed class AbortResult } /// Parameters for aborting the current turn. +[Experimental(Diagnostics.Experimental)] internal sealed class AbortRequest { /// Finite reason code describing why the current turn was aborted. @@ -1358,6 +1374,7 @@ internal sealed class AbortRequest } /// Parameters for shutting down the session. +[Experimental(Diagnostics.Experimental)] internal sealed class ShutdownRequest { /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. @@ -1374,6 +1391,7 @@ internal sealed class ShutdownRequest } /// Identifier of the session event that was emitted for the log message. +[Experimental(Diagnostics.Experimental)] public sealed class LogResult { /// The unique identifier of the emitted session event. @@ -1382,6 +1400,7 @@ public sealed class LogResult } /// Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. +[Experimental(Diagnostics.Experimental)] internal sealed class LogRequest { /// When true, the message is transient and not persisted to the session event log on disk. @@ -1416,6 +1435,7 @@ internal sealed class LogRequest } /// Authentication status and account metadata for the session. +[Experimental(Diagnostics.Experimental)] public sealed class SessionAuthStatus { /// Authentication type. @@ -1446,6 +1466,7 @@ public sealed class SessionAuthStatus } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionAuthGetStatusRequest { /// Target session identifier. @@ -1454,6 +1475,7 @@ internal sealed class SessionAuthGetStatusRequest } /// Indicates whether the credential update succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class SessionSetCredentialsResult { /// Whether the operation succeeded. @@ -1463,6 +1485,7 @@ public sealed class SessionSetCredentialsResult /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. /// Polymorphic base type discriminated by type. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -1482,6 +1505,7 @@ public partial class AuthInfo /// Schema for the `CopilotUserResponseEndpoints` type. +[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseEndpoints { /// Gets or sets the api value. @@ -1514,6 +1538,7 @@ public sealed class CopilotUserResponseOrganizationListItem } /// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. +[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshotsChat { /// Gets or sets the entitlement value. @@ -1566,6 +1591,7 @@ public sealed class CopilotUserResponseQuotaSnapshotsChat } /// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. +[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshotsCompletions { /// Gets or sets the entitlement value. @@ -1618,6 +1644,7 @@ public sealed class CopilotUserResponseQuotaSnapshotsCompletions } /// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. +[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshotsPremiumInteractions { /// Gets or sets the entitlement value. @@ -1670,6 +1697,7 @@ public sealed class CopilotUserResponseQuotaSnapshotsPremiumInteractions } /// Schema for the `CopilotUserResponseQuotaSnapshots` type. +[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponseQuotaSnapshots { /// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. @@ -1686,6 +1714,7 @@ public sealed class CopilotUserResponseQuotaSnapshots } /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. +[Experimental(Diagnostics.Experimental)] public sealed class CopilotUserResponse { /// Gets or sets the access_type_sku value. @@ -1783,6 +1812,7 @@ public sealed class CopilotUserResponse /// Schema for the `HMACAuthInfo` type. /// The hmac variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoHmac : AuthInfo { /// @@ -1805,6 +1835,7 @@ public partial class AuthInfoHmac : AuthInfo /// Schema for the `EnvAuthInfo` type. /// The env variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoEnv : AuthInfo { /// @@ -1836,6 +1867,7 @@ public partial class AuthInfoEnv : AuthInfo /// Schema for the `TokenAuthInfo` type. /// The token variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoToken : AuthInfo { /// @@ -1858,6 +1890,7 @@ public partial class AuthInfoToken : AuthInfo /// Schema for the `CopilotApiTokenAuthInfo` type. /// The copilot-api-token variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoCopilotApiToken : AuthInfo { /// @@ -1876,6 +1909,7 @@ public partial class AuthInfoCopilotApiToken : AuthInfo /// Schema for the `UserAuthInfo` type. /// The user variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoUser : AuthInfo { /// @@ -1898,6 +1932,7 @@ public partial class AuthInfoUser : AuthInfo /// Schema for the `GhCliAuthInfo` type. /// The gh-cli variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoGhCli : AuthInfo { /// @@ -1924,6 +1959,7 @@ public partial class AuthInfoGhCli : AuthInfo /// Schema for the `ApiKeyAuthInfo` type. /// The api-key variant of . +[Experimental(Diagnostics.Experimental)] public partial class AuthInfoApiKey : AuthInfo { /// @@ -1945,6 +1981,7 @@ public partial class AuthInfoApiKey : AuthInfo } /// New auth credentials to install on the session. Omit to leave credentials unchanged. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionSetCredentialsParams { /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. @@ -1957,6 +1994,7 @@ internal sealed class SessionSetCredentialsParams } /// The currently selected model and reasoning effort for the session. +[Experimental(Diagnostics.Experimental)] public sealed class CurrentModel { /// Currently active model identifier. @@ -1969,6 +2007,7 @@ public sealed class CurrentModel } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionModelGetCurrentRequest { /// Target session identifier. @@ -1977,6 +2016,7 @@ internal sealed class SessionModelGetCurrentRequest } /// The model identifier active on the session after the switch. +[Experimental(Diagnostics.Experimental)] public sealed class ModelSwitchToResult { /// Currently active model identifier after the switch. @@ -1985,6 +2025,7 @@ public sealed class ModelSwitchToResult } /// Vision-specific limits. +[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverrideLimitsVision { /// Maximum image size in bytes. @@ -2001,6 +2042,7 @@ public sealed class ModelCapabilitiesOverrideLimitsVision } /// Token limits for prompts, outputs, and context window. +[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverrideLimits { /// Maximum total context window size in tokens. @@ -2021,6 +2063,7 @@ public sealed class ModelCapabilitiesOverrideLimits } /// Feature flags indicating what the model supports. +[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverrideSupports { /// Whether this model supports reasoning effort configuration. @@ -2033,6 +2076,7 @@ public sealed class ModelCapabilitiesOverrideSupports } /// Override individual model capabilities resolved by the runtime. +[Experimental(Diagnostics.Experimental)] public sealed class ModelCapabilitiesOverride { /// Token limits for prompts, outputs, and context window. @@ -2045,6 +2089,7 @@ public sealed class ModelCapabilitiesOverride } /// Target model identifier and optional reasoning effort, summary, and capability overrides. +[Experimental(Diagnostics.Experimental)] internal sealed class ModelSwitchToRequest { /// Override individual model capabilities resolved by the runtime. @@ -2069,6 +2114,7 @@ internal sealed class ModelSwitchToRequest } /// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. +[Experimental(Diagnostics.Experimental)] public sealed class ModelSetReasoningEffortResult { /// Reasoning effort level recorded on the session after the update. @@ -2077,6 +2123,7 @@ public sealed class ModelSetReasoningEffortResult } /// Reasoning effort level to apply to the currently selected model. +[Experimental(Diagnostics.Experimental)] internal sealed class ModelSetReasoningEffortRequest { /// Reasoning effort level to apply to the currently selected model. The host is responsible for validating the value against the model's supported levels before calling. @@ -2089,6 +2136,7 @@ internal sealed class ModelSetReasoningEffortRequest } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionModeGetRequest { /// Target session identifier. @@ -2097,6 +2145,7 @@ internal sealed class SessionModeGetRequest } /// Agent interaction mode to apply to the session. +[Experimental(Diagnostics.Experimental)] internal sealed class ModeSetRequest { /// The session mode the agent is operating in. @@ -2109,6 +2158,7 @@ internal sealed class ModeSetRequest } /// The session's friendly name, or null when not yet set. +[Experimental(Diagnostics.Experimental)] public sealed class NameGetResult { /// The session name (user-set or auto-generated), or null if not yet set. @@ -2117,6 +2167,7 @@ public sealed class NameGetResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionNameGetRequest { /// Target session identifier. @@ -2125,6 +2176,7 @@ internal sealed class SessionNameGetRequest } /// New friendly name to apply to the session. +[Experimental(Diagnostics.Experimental)] internal sealed class NameSetRequest { /// New session name (1–100 characters, trimmed of leading/trailing whitespace). @@ -2140,6 +2192,7 @@ internal sealed class NameSetRequest } /// Indicates whether the auto-generated summary was applied as the session's name. +[Experimental(Diagnostics.Experimental)] public sealed class NameSetAutoResult { /// Whether the auto-generated summary was persisted. False if the session already has a user-set name, the summary normalized to empty, or the session does not have a workspace. @@ -2148,6 +2201,7 @@ public sealed class NameSetAutoResult } /// Auto-generated session summary to apply as the session's name when no user-set name exists. +[Experimental(Diagnostics.Experimental)] internal sealed class NameSetAutoRequest { /// Target session identifier. @@ -2160,6 +2214,7 @@ internal sealed class NameSetAutoRequest } /// Existence, contents, and resolved path of the session plan file. +[Experimental(Diagnostics.Experimental)] public sealed class PlanReadResult { /// The content of the plan file, or null if it does not exist. @@ -2176,6 +2231,7 @@ public sealed class PlanReadResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionPlanReadRequest { /// Target session identifier. @@ -2184,6 +2240,7 @@ internal sealed class SessionPlanReadRequest } /// Replacement contents to write to the session plan file. +[Experimental(Diagnostics.Experimental)] internal sealed class PlanUpdateRequest { /// The new content for the plan file. @@ -2196,6 +2253,7 @@ internal sealed class PlanUpdateRequest } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionPlanDeleteRequest { /// Target session identifier. @@ -2226,13 +2284,15 @@ public sealed class WorkspacesGetWorkspaceResultWorkspace [JsonPropertyName("git_root")] public string? GitRoot { get; set; } - /// Gets or sets the host_type value. + /// Allowed values for the `WorkspacesWorkspaceDetailsHostType` enumeration. [JsonPropertyName("host_type")] - public WorkspacesGetWorkspaceResultWorkspaceHostType? HostType { get; set; } + public WorkspacesWorkspaceDetailsHostType? HostType { get; set; } /// Gets or sets the id value. + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] + [MinLength(1)] [JsonPropertyName("id")] - public Guid Id { get; set; } + public string Id { get; set; } = string.Empty; /// Gets or sets the mc_last_event_id value. [JsonPropertyName("mc_last_event_id")] @@ -2272,6 +2332,7 @@ public sealed class WorkspacesGetWorkspaceResultWorkspace } /// Current workspace metadata for the session, including its absolute filesystem path when available. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesGetWorkspaceResult { /// Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). @@ -2284,6 +2345,7 @@ public sealed class WorkspacesGetWorkspaceResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionWorkspacesGetWorkspaceRequest { /// Target session identifier. @@ -2292,6 +2354,7 @@ internal sealed class SessionWorkspacesGetWorkspaceRequest } /// Relative paths of files stored in the session workspace files directory. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesListFilesResult { /// Relative file paths in the workspace files directory. @@ -2300,6 +2363,7 @@ public sealed class WorkspacesListFilesResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionWorkspacesListFilesRequest { /// Target session identifier. @@ -2308,6 +2372,7 @@ internal sealed class SessionWorkspacesListFilesRequest } /// Contents of the requested workspace file as a UTF-8 string. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesReadFileResult { /// File content as a UTF-8 string. @@ -2316,6 +2381,7 @@ public sealed class WorkspacesReadFileResult } /// Relative path of the workspace file to read. +[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesReadFileRequest { /// Relative path within the workspace files directory. @@ -2328,6 +2394,7 @@ internal sealed class WorkspacesReadFileRequest } /// Relative path and UTF-8 content for the workspace file to create or overwrite. +[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesCreateFileRequest { /// File content to write as a UTF-8 string. @@ -2344,6 +2411,7 @@ internal sealed class WorkspacesCreateFileRequest } /// Schema for the `WorkspacesCheckpoints` type. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesCheckpoints { /// Filename of the checkpoint within the workspace checkpoints directory. @@ -2360,6 +2428,7 @@ public sealed class WorkspacesCheckpoints } /// Workspace checkpoints in chronological order; empty when the workspace is not enabled. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesListCheckpointsResult { /// Workspace checkpoints in chronological order. Empty when workspace is not enabled. @@ -2368,6 +2437,7 @@ public sealed class WorkspacesListCheckpointsResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionWorkspacesListCheckpointsRequest { /// Target session identifier. @@ -2376,6 +2446,7 @@ internal sealed class SessionWorkspacesListCheckpointsRequest } /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesReadCheckpointResult { /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. @@ -2384,6 +2455,7 @@ public sealed class WorkspacesReadCheckpointResult } /// Checkpoint number to read. +[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesReadCheckpointRequest { /// Checkpoint number to read. @@ -2412,6 +2484,7 @@ public sealed class WorkspacesSaveLargePasteResultSaved } /// Descriptor for the saved paste file, or null when the workspace is unavailable. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesSaveLargePasteResult { /// Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions). @@ -2420,6 +2493,7 @@ public sealed class WorkspacesSaveLargePasteResult } /// Pasted content to save as a UTF-8 file in the session workspace. +[Experimental(Diagnostics.Experimental)] internal sealed class WorkspacesSaveLargePasteRequest { /// Pasted content to save as a UTF-8 file. @@ -2432,6 +2506,7 @@ internal sealed class WorkspacesSaveLargePasteRequest } /// Schema for the `InstructionsSources` type. +[Experimental(Diagnostics.Experimental)] public sealed class InstructionsSources { /// Glob pattern(s) from frontmatter — when set, this instruction applies only to matching files. @@ -2472,6 +2547,7 @@ public sealed class InstructionsSources } /// Instruction sources loaded for the session, in merge order. +[Experimental(Diagnostics.Experimental)] public sealed class InstructionsGetSourcesResult { /// Instruction sources for the session. @@ -2480,6 +2556,7 @@ public sealed class InstructionsGetSourcesResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionInstructionsGetSourcesRequest { /// Target session identifier. @@ -2893,13 +2970,76 @@ internal sealed class SessionTasksWaitForPendingRequest public string SessionId { get; set; } = string.Empty; } +/// Polymorphic base type discriminated by type. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "type", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(TasksGetProgressResultProgressAgent), "agent")] +[JsonDerivedType(typeof(TasksGetProgressResultProgressShell), "shell")] +public partial class TasksGetProgressResultProgress +{ + /// The type discriminator. + [JsonPropertyName("type")] + public virtual string Type { get; set; } = string.Empty; +} + + +/// Schema for the `TaskProgressLine` type. +[Experimental(Diagnostics.Experimental)] +public sealed class TaskProgressLine +{ + /// Display message, e.g., "▸ bash", "✓ edit src/foo.ts". + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; + + /// ISO 8601 timestamp when this event occurred. + [JsonPropertyName("timestamp")] + public DateTimeOffset Timestamp { get; set; } +} + +/// Schema for the `TaskAgentProgress` type. +/// The agent variant of . +public partial class TasksGetProgressResultProgressAgent : TasksGetProgressResultProgress +{ + /// + [JsonIgnore] + public override string Type => "agent"; + + /// The most recent intent reported by the agent. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("latestIntent")] + public string? LatestIntent { get; set; } + + /// Recent tool execution events converted to display lines. + [JsonPropertyName("recentActivity")] + public required IList RecentActivity { get; set; } +} + +/// Schema for the `TaskShellProgress` type. +/// The shell variant of . +public partial class TasksGetProgressResultProgressShell : TasksGetProgressResultProgress +{ + /// + [JsonIgnore] + public override string Type => "shell"; + + /// Process ID when available. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("pid")] + public long? Pid { get; set; } + + /// Recent stdout/stderr lines from the running shell command. + [JsonPropertyName("recentOutput")] + public required string RecentOutput { get; set; } +} + /// Progress information for the task, or null when no task with that ID is tracked. [Experimental(Diagnostics.Experimental)] public sealed class TasksGetProgressResult { /// Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. [JsonPropertyName("progress")] - public object? Progress { get; set; } + public TasksGetProgressResultProgress? Progress { get; set; } } /// Identifier of the background task to fetch progress for. @@ -3774,6 +3914,7 @@ internal sealed class SessionExtensionsReloadRequest } /// Indicates whether the external tool call result was handled successfully. +[Experimental(Diagnostics.Experimental)] public sealed class HandlePendingToolCallResult { /// Whether the tool call result was handled successfully. @@ -3782,6 +3923,7 @@ public sealed class HandlePendingToolCallResult } /// Pending external tool call request ID, with the tool result or an error describing why it failed. +[Experimental(Diagnostics.Experimental)] internal sealed class HandlePendingToolCallRequest { /// Error message if the tool call failed. @@ -3802,11 +3944,13 @@ internal sealed class HandlePendingToolCallRequest } /// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. +[Experimental(Diagnostics.Experimental)] public sealed class ToolsInitializeAndValidateResult { } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionToolsInitializeAndValidateRequest { /// Target session identifier. @@ -3815,6 +3959,7 @@ internal sealed class SessionToolsInitializeAndValidateRequest } /// Optional unstructured input hint. +[Experimental(Diagnostics.Experimental)] public sealed class SlashCommandInput { /// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). @@ -3835,6 +3980,7 @@ public sealed class SlashCommandInput } /// Schema for the `SlashCommandInfo` type. +[Experimental(Diagnostics.Experimental)] public sealed class SlashCommandInfo { /// Canonical aliases without leading slashes. @@ -3867,6 +4013,7 @@ public sealed class SlashCommandInfo } /// Slash commands available in the session, after applying any include/exclude filters. +[Experimental(Diagnostics.Experimental)] public sealed class CommandList { /// Commands available in this session. @@ -3875,6 +4022,7 @@ public sealed class CommandList } /// Optional filters controlling which command sources to include in the listing. +[Experimental(Diagnostics.Experimental)] public sealed class CommandsListRequest { /// Include runtime built-in commands. @@ -3891,6 +4039,7 @@ public sealed class CommandsListRequest } /// Optional filters controlling which command sources to include in the listing. +[Experimental(Diagnostics.Experimental)] internal sealed class CommandsListRequestWithSession { /// Include runtime built-in commands. @@ -3912,12 +4061,14 @@ internal sealed class CommandsListRequestWithSession /// Result of invoking the slash command (text output, prompt to send to the agent, or completion). /// Polymorphic base type discriminated by kind. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] [JsonDerivedType(typeof(SlashCommandInvocationResultText), "text")] [JsonDerivedType(typeof(SlashCommandInvocationResultAgentPrompt), "agent-prompt")] [JsonDerivedType(typeof(SlashCommandInvocationResultCompleted), "completed")] +[JsonDerivedType(typeof(SlashCommandInvocationResultSelectSubcommand), "select-subcommand")] public partial class SlashCommandInvocationResult { /// The type discriminator. @@ -3928,6 +4079,7 @@ public partial class SlashCommandInvocationResult /// Schema for the `SlashCommandTextResult` type. /// The text variant of . +[Experimental(Diagnostics.Experimental)] public partial class SlashCommandInvocationResultText : SlashCommandInvocationResult { /// @@ -3956,6 +4108,7 @@ public partial class SlashCommandInvocationResultText : SlashCommandInvocationRe /// Schema for the `SlashCommandAgentPromptResult` type. /// The agent-prompt variant of . +[Experimental(Diagnostics.Experimental)] public partial class SlashCommandInvocationResultAgentPrompt : SlashCommandInvocationResult { /// @@ -3983,6 +4136,7 @@ public partial class SlashCommandInvocationResultAgentPrompt : SlashCommandInvoc /// Schema for the `SlashCommandCompletedResult` type. /// The completed variant of . +[Experimental(Diagnostics.Experimental)] public partial class SlashCommandInvocationResultCompleted : SlashCommandInvocationResult { /// @@ -4000,7 +4154,52 @@ public partial class SlashCommandInvocationResultCompleted : SlashCommandInvocat public bool? RuntimeSettingsChanged { get; set; } } +/// Schema for the `SlashCommandSelectSubcommandOption` type. +[Experimental(Diagnostics.Experimental)] +public sealed class SlashCommandSelectSubcommandOption +{ + /// Human-readable description of the subcommand. + [JsonPropertyName("description")] + public string Description { get; set; } = string.Empty; + + /// Optional group label for organizing options. + [JsonPropertyName("group")] + public string? Group { get; set; } + + /// Subcommand name to invoke. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; +} + +/// Schema for the `SlashCommandSelectSubcommandResult` type. +/// The select-subcommand variant of . +[Experimental(Diagnostics.Experimental)] +public partial class SlashCommandInvocationResultSelectSubcommand : SlashCommandInvocationResult +{ + /// + [JsonIgnore] + public override string Kind => "select-subcommand"; + + /// Parent command name that requires subcommand selection. + [JsonPropertyName("command")] + public required string Command { get; set; } + + /// Available subcommand options for the client to present. + [JsonPropertyName("options")] + public required IList Options { get; set; } + + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("runtimeSettingsChanged")] + public bool? RuntimeSettingsChanged { get; set; } + + /// Human-readable title for the selection UI. + [JsonPropertyName("title")] + public required string Title { get; set; } +} + /// Slash command name and optional raw input string to invoke. +[Experimental(Diagnostics.Experimental)] internal sealed class CommandsInvokeRequest { /// Raw input after the command name. @@ -4017,6 +4216,7 @@ internal sealed class CommandsInvokeRequest } /// Indicates whether the pending client-handled command was completed successfully. +[Experimental(Diagnostics.Experimental)] public sealed class CommandsHandlePendingCommandResult { /// Whether the command was handled successfully. @@ -4025,6 +4225,7 @@ public sealed class CommandsHandlePendingCommandResult } /// Pending command request ID and an optional error if the client handler failed. +[Experimental(Diagnostics.Experimental)] internal sealed class CommandsHandlePendingCommandRequest { /// Error message if the command handler failed. @@ -4041,6 +4242,7 @@ internal sealed class CommandsHandlePendingCommandRequest } /// Error message produced while executing the command, if any. +[Experimental(Diagnostics.Experimental)] public sealed class ExecuteCommandResult { /// Error message produced while executing the command, if any. Omitted when the handler succeeded. @@ -4049,6 +4251,7 @@ public sealed class ExecuteCommandResult } /// Slash command name and argument string to execute synchronously. +[Experimental(Diagnostics.Experimental)] internal sealed class ExecuteCommandParams { /// Argument string to pass to the command (empty string if none). @@ -4065,6 +4268,7 @@ internal sealed class ExecuteCommandParams } /// Indicates whether the command was accepted into the local execution queue. +[Experimental(Diagnostics.Experimental)] public sealed class EnqueueCommandResult { /// True when the command was accepted into the local execution queue. False when the call targets a session that does not support local command queueing (e.g. remote sessions). @@ -4073,6 +4277,7 @@ public sealed class EnqueueCommandResult } /// Slash-prefixed command string to enqueue for FIFO processing. +[Experimental(Diagnostics.Experimental)] internal sealed class EnqueueCommandParams { /// Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO with any in-flight items; if the session is idle, processing kicks off immediately. @@ -4085,6 +4290,7 @@ internal sealed class EnqueueCommandParams } /// Indicates whether the queued-command response was matched to a pending request. +[Experimental(Diagnostics.Experimental)] public sealed class CommandsRespondToQueuedCommandResult { /// Whether a pending queued command with the given request ID was found and resolved. False when the request was already resolved, cancelled, or unknown. @@ -4094,6 +4300,7 @@ public sealed class CommandsRespondToQueuedCommandResult /// Result of the queued command execution. /// Data type discriminated by handled. +[Experimental(Diagnostics.Experimental)] public partial class QueuedCommandResult { /// The boolean discriminator. @@ -4107,6 +4314,7 @@ public partial class QueuedCommandResult } /// Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). +[Experimental(Diagnostics.Experimental)] internal sealed class CommandsRespondToQueuedCommandRequest { /// Request ID from the `command.queued` event the host is responding to. @@ -4136,6 +4344,7 @@ internal sealed class TelemetrySetFeatureOverridesRequest } /// The elicitation response (accept with form values, decline, or cancel). +[Experimental(Diagnostics.Experimental)] public sealed class UIElicitationResponse { /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). @@ -4148,6 +4357,7 @@ public sealed class UIElicitationResponse } /// JSON Schema describing the form fields to present to the user. +[Experimental(Diagnostics.Experimental)] public sealed class UIElicitationSchema { /// Form field definitions, keyed by field name. @@ -4164,6 +4374,7 @@ public sealed class UIElicitationSchema } /// Prompt message and JSON schema describing the form fields to elicit from the user. +[Experimental(Diagnostics.Experimental)] internal sealed class UIElicitationRequest { /// Message describing what information is needed from the user. @@ -4180,6 +4391,7 @@ internal sealed class UIElicitationRequest } /// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. +[Experimental(Diagnostics.Experimental)] public sealed class UIElicitationResult { /// Whether the response was accepted. False if the request was already resolved by another client. @@ -4188,6 +4400,7 @@ public sealed class UIElicitationResult } /// Pending elicitation request ID and the user's response (accept/decline/cancel + form values). +[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingElicitationRequest { /// The unique request ID from the elicitation.requested event. @@ -4204,6 +4417,7 @@ internal sealed class UIHandlePendingElicitationRequest } /// Indicates whether the pending UI request was resolved by this call. +[Experimental(Diagnostics.Experimental)] public sealed class UIHandlePendingResult { /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. @@ -4212,6 +4426,7 @@ public sealed class UIHandlePendingResult } /// Schema for the `UIUserInputResponse` type. +[Experimental(Diagnostics.Experimental)] public sealed class UIUserInputResponse { /// The user's answer text. @@ -4224,6 +4439,7 @@ public sealed class UIUserInputResponse } /// Request ID of a pending `user_input.requested` event and the user's response. +[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingUserInputRequest { /// The unique request ID from the user_input.requested event. @@ -4240,11 +4456,13 @@ internal sealed class UIHandlePendingUserInputRequest } /// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. +[Experimental(Diagnostics.Experimental)] public sealed class UIHandlePendingSamplingResponse { } /// Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). +[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingSamplingRequest { /// The unique request ID from the sampling.requested event. @@ -4261,6 +4479,7 @@ internal sealed class UIHandlePendingSamplingRequest } /// Request ID of a pending `auto_mode_switch.requested` event and the user's response. +[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingAutoModeSwitchRequest { /// The unique request ID from the auto_mode_switch.requested event. @@ -4277,6 +4496,7 @@ internal sealed class UIHandlePendingAutoModeSwitchRequest } /// Schema for the `UIExitPlanModeResponse` type. +[Experimental(Diagnostics.Experimental)] public sealed class UIExitPlanModeResponse { /// Whether the plan was approved. @@ -4297,6 +4517,7 @@ public sealed class UIExitPlanModeResponse } /// Request ID of a pending `exit_plan_mode.requested` event and the user's response. +[Experimental(Diagnostics.Experimental)] internal sealed class UIHandlePendingExitPlanModeRequest { /// The unique request ID from the exit_plan_mode.requested event. @@ -4313,6 +4534,7 @@ internal sealed class UIHandlePendingExitPlanModeRequest } /// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). +[Experimental(Diagnostics.Experimental)] public sealed class UIRegisterDirectAutoModeSwitchHandlerResult { /// Opaque handle representing the registration. Pass this same handle to `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. Multiple registrations are reference-counted; the server bridge will only dispatch auto-mode-switch requests when no handles are active. @@ -4321,6 +4543,7 @@ public sealed class UIRegisterDirectAutoModeSwitchHandlerResult } /// Identifies the target session. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionUiRegisterDirectAutoModeSwitchHandlerRequest { /// Target session identifier. @@ -4329,6 +4552,7 @@ internal sealed class SessionUiRegisterDirectAutoModeSwitchHandlerRequest } /// Indicates whether the handle was active and the registration count was decremented. +[Experimental(Diagnostics.Experimental)] public sealed class UIUnregisterDirectAutoModeSwitchHandlerResult { /// True if the handle was active and decremented the counter; false if the handle was unknown. @@ -4337,6 +4561,7 @@ public sealed class UIUnregisterDirectAutoModeSwitchHandlerResult } /// Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. +[Experimental(Diagnostics.Experimental)] internal sealed class UIUnregisterDirectAutoModeSwitchHandlerRequest { /// Handle previously returned by `registerDirectAutoModeSwitchHandler`. @@ -4349,6 +4574,7 @@ internal sealed class UIUnregisterDirectAutoModeSwitchHandlerRequest } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureResult { /// Whether the operation succeeded. @@ -4357,6 +4583,7 @@ public sealed class PermissionsConfigureResult } /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRuleSource { /// Gets or sets the name value. @@ -4369,6 +4596,7 @@ public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRuleSour } /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRule { /// Gets or sets the ifAnyMatch value. @@ -4389,6 +4617,7 @@ public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRule } /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsConfigureAdditionalContentExclusionPolicy { /// Gets or sets the last_updated_at value. @@ -4405,6 +4634,7 @@ public sealed class PermissionsConfigureAdditionalContentExclusionPolicy } /// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionPathsConfig { /// Additional directories to allow tool access to (in addition to the session's working directory). When `unrestricted` is true, these are still pre-populated on the UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention completion). @@ -4425,6 +4655,7 @@ public sealed class PermissionPathsConfig } /// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionRulesSet { /// Rules that auto-approve matching requests. @@ -4437,6 +4668,7 @@ public sealed class PermissionRulesSet } /// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionUrlsConfig { /// Initial list of allowed URL/domain patterns. Patterns may include path components. Ignored when `unrestricted` is true. @@ -4449,6 +4681,7 @@ public sealed class PermissionUrlsConfig } /// Patch of permission policy fields to apply (omit a field to leave it unchanged). +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsConfigureParams { /// If specified, replaces the host-supplied GitHub Content Exclusion policies on the session (combined with natively-discovered policies when evaluating tool/file access). Omit to leave the current policies unchanged. @@ -4481,6 +4714,7 @@ internal sealed class PermissionsConfigureParams } /// Indicates whether the permission decision was applied; false when the request was already resolved. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionRequestResult { /// Whether the permission request was handled successfully. @@ -4490,6 +4724,7 @@ public sealed class PermissionRequestResult /// The client's response to the pending permission prompt. /// Polymorphic base type discriminated by kind. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -4518,6 +4753,7 @@ public partial class PermissionDecision /// Schema for the `PermissionDecisionApproveOnce` type. /// The approve-once variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveOnce : PermissionDecision { /// @@ -4527,6 +4763,7 @@ public partial class PermissionDecisionApproveOnce : PermissionDecision /// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts). /// Polymorphic base type discriminated by kind. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -4549,6 +4786,7 @@ public partial class PermissionDecisionApproveForSessionApproval /// Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type. /// The commands variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalCommands : PermissionDecisionApproveForSessionApproval { /// @@ -4562,6 +4800,7 @@ public partial class PermissionDecisionApproveForSessionApprovalCommands : Permi /// Schema for the `PermissionDecisionApproveForSessionApprovalRead` type. /// The read variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalRead : PermissionDecisionApproveForSessionApproval { /// @@ -4571,6 +4810,7 @@ public partial class PermissionDecisionApproveForSessionApprovalRead : Permissio /// Schema for the `PermissionDecisionApproveForSessionApprovalWrite` type. /// The write variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalWrite : PermissionDecisionApproveForSessionApproval { /// @@ -4580,6 +4820,7 @@ public partial class PermissionDecisionApproveForSessionApprovalWrite : Permissi /// Schema for the `PermissionDecisionApproveForSessionApprovalMcp` type. /// The mcp variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalMcp : PermissionDecisionApproveForSessionApproval { /// @@ -4597,6 +4838,7 @@ public partial class PermissionDecisionApproveForSessionApprovalMcp : Permission /// Schema for the `PermissionDecisionApproveForSessionApprovalMcpSampling` type. /// The mcp-sampling variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalMcpSampling : PermissionDecisionApproveForSessionApproval { /// @@ -4610,6 +4852,7 @@ public partial class PermissionDecisionApproveForSessionApprovalMcpSampling : Pe /// Schema for the `PermissionDecisionApproveForSessionApprovalMemory` type. /// The memory variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalMemory : PermissionDecisionApproveForSessionApproval { /// @@ -4619,6 +4862,7 @@ public partial class PermissionDecisionApproveForSessionApprovalMemory : Permiss /// Schema for the `PermissionDecisionApproveForSessionApprovalCustomTool` type. /// The custom-tool variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalCustomTool : PermissionDecisionApproveForSessionApproval { /// @@ -4632,6 +4876,7 @@ public partial class PermissionDecisionApproveForSessionApprovalCustomTool : Per /// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionManagement` type. /// The extension-management variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalExtensionManagement : PermissionDecisionApproveForSessionApproval { /// @@ -4646,6 +4891,7 @@ public partial class PermissionDecisionApproveForSessionApprovalExtensionManagem /// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` type. /// The extension-permission-access variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess : PermissionDecisionApproveForSessionApproval { /// @@ -4659,6 +4905,7 @@ public partial class PermissionDecisionApproveForSessionApprovalExtensionPermiss /// Schema for the `PermissionDecisionApproveForSession` type. /// The approve-for-session variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForSession : PermissionDecision { /// @@ -4678,6 +4925,7 @@ public partial class PermissionDecisionApproveForSession : PermissionDecision /// Approval to persist for this location. /// Polymorphic base type discriminated by kind. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( TypeDiscriminatorPropertyName = "kind", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] @@ -4700,6 +4948,7 @@ public partial class PermissionDecisionApproveForLocationApproval /// Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type. /// The commands variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalCommands : PermissionDecisionApproveForLocationApproval { /// @@ -4713,6 +4962,7 @@ public partial class PermissionDecisionApproveForLocationApprovalCommands : Perm /// Schema for the `PermissionDecisionApproveForLocationApprovalRead` type. /// The read variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalRead : PermissionDecisionApproveForLocationApproval { /// @@ -4722,6 +4972,7 @@ public partial class PermissionDecisionApproveForLocationApprovalRead : Permissi /// Schema for the `PermissionDecisionApproveForLocationApprovalWrite` type. /// The write variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalWrite : PermissionDecisionApproveForLocationApproval { /// @@ -4731,6 +4982,7 @@ public partial class PermissionDecisionApproveForLocationApprovalWrite : Permiss /// Schema for the `PermissionDecisionApproveForLocationApprovalMcp` type. /// The mcp variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalMcp : PermissionDecisionApproveForLocationApproval { /// @@ -4748,6 +5000,7 @@ public partial class PermissionDecisionApproveForLocationApprovalMcp : Permissio /// Schema for the `PermissionDecisionApproveForLocationApprovalMcpSampling` type. /// The mcp-sampling variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalMcpSampling : PermissionDecisionApproveForLocationApproval { /// @@ -4761,6 +5014,7 @@ public partial class PermissionDecisionApproveForLocationApprovalMcpSampling : P /// Schema for the `PermissionDecisionApproveForLocationApprovalMemory` type. /// The memory variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalMemory : PermissionDecisionApproveForLocationApproval { /// @@ -4770,6 +5024,7 @@ public partial class PermissionDecisionApproveForLocationApprovalMemory : Permis /// Schema for the `PermissionDecisionApproveForLocationApprovalCustomTool` type. /// The custom-tool variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalCustomTool : PermissionDecisionApproveForLocationApproval { /// @@ -4783,6 +5038,7 @@ public partial class PermissionDecisionApproveForLocationApprovalCustomTool : Pe /// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionManagement` type. /// The extension-management variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalExtensionManagement : PermissionDecisionApproveForLocationApproval { /// @@ -4797,6 +5053,7 @@ public partial class PermissionDecisionApproveForLocationApprovalExtensionManage /// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` type. /// The extension-permission-access variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess : PermissionDecisionApproveForLocationApproval { /// @@ -4810,6 +5067,7 @@ public partial class PermissionDecisionApproveForLocationApprovalExtensionPermis /// Schema for the `PermissionDecisionApproveForLocation` type. /// The approve-for-location variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproveForLocation : PermissionDecision { /// @@ -4827,6 +5085,7 @@ public partial class PermissionDecisionApproveForLocation : PermissionDecision /// Schema for the `PermissionDecisionApprovePermanently` type. /// The approve-permanently variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApprovePermanently : PermissionDecision { /// @@ -4840,6 +5099,7 @@ public partial class PermissionDecisionApprovePermanently : PermissionDecision /// Schema for the `PermissionDecisionReject` type. /// The reject variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionReject : PermissionDecision { /// @@ -4854,6 +5114,7 @@ public partial class PermissionDecisionReject : PermissionDecision /// Schema for the `PermissionDecisionUserNotAvailable` type. /// The user-not-available variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionUserNotAvailable : PermissionDecision { /// @@ -4863,6 +5124,7 @@ public partial class PermissionDecisionUserNotAvailable : PermissionDecision /// Schema for the `PermissionDecisionApproved` type. /// The approved variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApproved : PermissionDecision { /// @@ -4872,6 +5134,7 @@ public partial class PermissionDecisionApproved : PermissionDecision /// Schema for the `PermissionDecisionApprovedForSession` type. /// The approved-for-session variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApprovedForSession : PermissionDecision { /// @@ -4885,6 +5148,7 @@ public partial class PermissionDecisionApprovedForSession : PermissionDecision /// Schema for the `PermissionDecisionApprovedForLocation` type. /// The approved-for-location variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionApprovedForLocation : PermissionDecision { /// @@ -4902,6 +5166,7 @@ public partial class PermissionDecisionApprovedForLocation : PermissionDecision /// Schema for the `PermissionDecisionCancelled` type. /// The cancelled variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionCancelled : PermissionDecision { /// @@ -4916,6 +5181,7 @@ public partial class PermissionDecisionCancelled : PermissionDecision /// Schema for the `PermissionDecisionDeniedByRules` type. /// The denied-by-rules variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedByRules : PermissionDecision { /// @@ -4929,6 +5195,7 @@ public partial class PermissionDecisionDeniedByRules : PermissionDecision /// Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. /// The denied-no-approval-rule-and-could-not-request-from-user variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser : PermissionDecision { /// @@ -4938,6 +5205,7 @@ public partial class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFro /// Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. /// The denied-interactively-by-user variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedInteractivelyByUser : PermissionDecision { /// @@ -4957,6 +5225,7 @@ public partial class PermissionDecisionDeniedInteractivelyByUser : PermissionDec /// Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. /// The denied-by-content-exclusion-policy variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedByContentExclusionPolicy : PermissionDecision { /// @@ -4974,6 +5243,7 @@ public partial class PermissionDecisionDeniedByContentExclusionPolicy : Permissi /// Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. /// The denied-by-permission-request-hook variant of . +[Experimental(Diagnostics.Experimental)] public partial class PermissionDecisionDeniedByPermissionRequestHook : PermissionDecision { /// @@ -4992,6 +5262,7 @@ public partial class PermissionDecisionDeniedByPermissionRequestHook : Permissio } /// Pending permission request ID and the decision to apply (approve/reject and scope). +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionDecisionRequest { /// Request ID of the pending permission request. @@ -5008,6 +5279,7 @@ internal sealed class PermissionDecisionRequest } /// Schema for the `PendingPermissionRequest` type. +[Experimental(Diagnostics.Experimental)] public sealed class PendingPermissionRequest { /// The user-facing permission prompt details (commands, write, read, mcp, url, memory, custom-tool, path, hook). @@ -5020,6 +5292,7 @@ public sealed class PendingPermissionRequest } /// List of pending permission requests reconstructed from event history. +[Experimental(Diagnostics.Experimental)] public sealed class PendingPermissionRequestList { /// Pending permission prompts reconstructed from the session's event history. Equivalent to the set of `permission.requested` events that have not yet been followed by a matching `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts that were emitted before the client attached to the session. @@ -5028,6 +5301,7 @@ public sealed class PendingPermissionRequestList } /// No parameters; returns currently-pending permission requests for the session. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsPendingRequestsRequest { /// Target session identifier. @@ -5036,6 +5310,7 @@ internal sealed class PermissionsPendingRequestsRequest } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsSetApproveAllResult { /// Whether the operation succeeded. @@ -5044,6 +5319,7 @@ public sealed class PermissionsSetApproveAllResult } /// Allow-all toggle for tool permission requests, with an optional telemetry source. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsSetApproveAllRequest { /// Whether to auto-approve all tool permission requests. @@ -5060,6 +5336,7 @@ internal sealed class PermissionsSetApproveAllRequest } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsModifyRulesResult { /// Whether the operation succeeded. @@ -5068,6 +5345,7 @@ public sealed class PermissionsModifyRulesResult } /// Scope and add/remove instructions for modifying session- or location-scoped permission rules. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsModifyRulesParams { /// Rules to add to the scope. Applied before `remove`/`removeAll`. @@ -5092,6 +5370,7 @@ internal sealed class PermissionsModifyRulesParams } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsSetRequiredResult { /// Whether the operation succeeded. @@ -5100,6 +5379,7 @@ public sealed class PermissionsSetRequiredResult } /// Toggles whether permission prompts should be bridged into session events for this client. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsSetRequiredRequest { /// Whether the client wants `permission.requested` events bridged from the session-owned permission service. CLI clients that render prompt UI set this to `true` for as long as their listener is mounted; headless callers leave it unset (the default is `false`). @@ -5112,6 +5392,7 @@ internal sealed class PermissionsSetRequiredRequest } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsResetSessionApprovalsResult { /// Whether the operation succeeded. @@ -5120,6 +5401,7 @@ public sealed class PermissionsResetSessionApprovalsResult } /// No parameters; clears all session-scoped tool permission approvals. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionsResetSessionApprovalsRequest { /// Target session identifier. @@ -5128,6 +5410,7 @@ internal sealed class PermissionsResetSessionApprovalsRequest } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsNotifyPromptShownResult { /// Whether the operation succeeded. @@ -5136,89 +5419,378 @@ public sealed class PermissionsNotifyPromptShownResult } /// Notification payload describing the permission prompt that the client just rendered. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionPromptShownNotification { /// Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). [JsonPropertyName("message")] public string Message { get; set; } = string.Empty; - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Snapshot of the session's allow-listed directories and primary working directory. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionPathsList +{ + /// All directories currently allowed for tool access on this session. + [JsonPropertyName("directories")] + public IList Directories { get => field ??= []; set; } + + /// The primary working directory for this session. + [JsonPropertyName("primary")] + public string Primary { get; set; } = string.Empty; +} + +/// No parameters; returns the session's allow-listed directories. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionsPathsListRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionsPathsAddResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} + +/// Directory path to add to the session's allowed directories. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionPathsAddParams +{ + /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionsPathsUpdatePrimaryResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} + +/// Directory path to set as the session's new primary working directory. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionPathsUpdatePrimaryParams +{ + /// Directory to set as the new primary working directory for the session's permission policy. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the supplied path is within the session's allowed directories. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionPathsAllowedCheckResult +{ + /// Whether the path is within the session's allowed directories. + [JsonPropertyName("allowed")] + public bool Allowed { get; set; } +} + +/// Path to evaluate against the session's allowed directories. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionPathsAllowedCheckParams +{ + /// Path to check against the session's allowed directories. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the supplied path is within the session's workspace directory. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionPathsWorkspaceCheckResult +{ + /// Whether the path is within the session workspace directory. + [JsonPropertyName("allowed")] + public bool Allowed { get; set; } +} + +/// Path to evaluate against the session's workspace (primary) directory. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionPathsWorkspaceCheckParams +{ + /// Path to check against the session workspace directory. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Resolved location-permissions key and type. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionLocationResolveResult +{ + /// Location key used in the location-permissions store. + [JsonPropertyName("locationKey")] + public string LocationKey { get; set; } = string.Empty; + + /// Whether the location is a git repo or directory. + [JsonPropertyName("locationType")] + public PermissionLocationType LocationType { get; set; } +} + +/// Working directory to resolve into a location-permissions key. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionLocationResolveParams +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Working directory whose permission location should be resolved. + [JsonPropertyName("workingDirectory")] + public string WorkingDirectory { get; set; } = string.Empty; +} + +/// Summary of persisted location permissions applied to the session. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionLocationApplyResult +{ + /// Number of persisted allowed directories added to the live path manager. + [JsonPropertyName("appliedDirectoryCount")] + public long AppliedDirectoryCount { get; set; } + + /// Number of location-scoped rules added to the live permission service. + [JsonPropertyName("appliedRuleCount")] + public long AppliedRuleCount { get; set; } + + /// Location-scoped rules applied to the live permission service. + [JsonPropertyName("appliedRules")] + public IList AppliedRules { get => field ??= []; set; } + + /// Whether a different location was applied since the previous apply call. + [JsonPropertyName("changed")] + public bool Changed { get; set; } + + /// Location key used in the location-permissions store. + [JsonPropertyName("locationKey")] + public string LocationKey { get; set; } = string.Empty; + + /// Whether the location is a git repo or directory. + [JsonPropertyName("locationType")] + public PermissionLocationType LocationType { get; set; } +} + +/// Working directory to load persisted location permissions for. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionLocationApplyParams +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Working directory whose persisted location permissions should be applied. + [JsonPropertyName("workingDirectory")] + public string WorkingDirectory { get; set; } = string.Empty; +} + +/// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionsLocationsAddToolApprovalResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} + +/// Tool approval to persist and apply. +/// Polymorphic base type discriminated by kind. +[Experimental(Diagnostics.Experimental)] +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "kind", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsCommands), "commands")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsRead), "read")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsWrite), "write")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsMcp), "mcp")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsMcpSampling), "mcp-sampling")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsMemory), "memory")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsCustomTool), "custom-tool")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsExtensionManagement), "extension-management")] +[JsonDerivedType(typeof(PermissionsLocationsAddToolApprovalDetailsExtensionPermissionAccess), "extension-permission-access")] +public partial class PermissionsLocationsAddToolApprovalDetails +{ + /// The type discriminator. + [JsonPropertyName("kind")] + public virtual string Kind { get; set; } = string.Empty; +} + + +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsCommands` type. +/// The commands variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsCommands : PermissionsLocationsAddToolApprovalDetails +{ + /// + [JsonIgnore] + public override string Kind => "commands"; + + /// Command identifiers covered by this approval. + [JsonPropertyName("commandIdentifiers")] + public required IList CommandIdentifiers { get; set; } +} + +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsRead` type. +/// The read variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsRead : PermissionsLocationsAddToolApprovalDetails +{ + /// + [JsonIgnore] + public override string Kind => "read"; +} + +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsWrite` type. +/// The write variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsWrite : PermissionsLocationsAddToolApprovalDetails +{ + /// + [JsonIgnore] + public override string Kind => "write"; +} + +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsMcp` type. +/// The mcp variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsMcp : PermissionsLocationsAddToolApprovalDetails +{ + /// + [JsonIgnore] + public override string Kind => "mcp"; + + /// MCP server name. + [JsonPropertyName("serverName")] + public required string ServerName { get; set; } + + /// MCP tool name, or null to cover every tool on the server. + [JsonPropertyName("toolName")] + public string? ToolName { get; set; } } -/// Snapshot of the session's allow-listed directories and primary working directory. -public sealed class PermissionPathsList +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsMcpSampling` type. +/// The mcp-sampling variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsMcpSampling : PermissionsLocationsAddToolApprovalDetails { - /// All directories currently allowed for tool access on this session. - [JsonPropertyName("directories")] - public IList Directories { get => field ??= []; set; } + /// + [JsonIgnore] + public override string Kind => "mcp-sampling"; - /// The primary working directory for this session. - [JsonPropertyName("primary")] - public string Primary { get; set; } = string.Empty; + /// MCP server name. + [JsonPropertyName("serverName")] + public required string ServerName { get; set; } } -/// No parameters; returns the session's allow-listed directories. -internal sealed class PermissionsPathsListRequest +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsMemory` type. +/// The memory variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsMemory : PermissionsLocationsAddToolApprovalDetails { - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// + [JsonIgnore] + public override string Kind => "memory"; } -/// Indicates whether the operation succeeded. -public sealed class PermissionsPathsAddResult +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsCustomTool` type. +/// The custom-tool variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsCustomTool : PermissionsLocationsAddToolApprovalDetails { - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// + [JsonIgnore] + public override string Kind => "custom-tool"; + + /// Custom tool name. + [JsonPropertyName("toolName")] + public required string ToolName { get; set; } } -/// Directory path to add to the session's allowed directories. -internal sealed class PermissionPathsAddParams +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsExtensionManagement` type. +/// The extension-management variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsExtensionManagement : PermissionsLocationsAddToolApprovalDetails { - /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// + [JsonIgnore] + public override string Kind => "extension-management"; - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Optional operation identifier; when omitted, the approval covers all extension management operations. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("operation")] + public string? Operation { get; set; } } -/// Indicates whether the operation succeeded. -public sealed class PermissionsPathsUpdatePrimaryResult +/// Schema for the `PermissionsLocationsAddToolApprovalDetailsExtensionPermissionAccess` type. +/// The extension-permission-access variant of . +[Experimental(Diagnostics.Experimental)] +public partial class PermissionsLocationsAddToolApprovalDetailsExtensionPermissionAccess : PermissionsLocationsAddToolApprovalDetails { - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// + [JsonIgnore] + public override string Kind => "extension-permission-access"; + + /// Extension name. + [JsonPropertyName("extensionName")] + public required string ExtensionName { get; set; } } -/// Directory path to set as the session's new primary working directory. -internal sealed class PermissionPathsUpdatePrimaryParams +/// Location-scoped tool approval to persist. +[Experimental(Diagnostics.Experimental)] +internal sealed class PermissionLocationAddToolApprovalParams { - /// Directory to set as the new primary working directory for the session's permission policy. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Tool approval to persist and apply. + [JsonPropertyName("approval")] + public PermissionsLocationsAddToolApprovalDetails Approval { get => field ??= new(); set; } + + /// Location key (git root or cwd) to persist the approval to. + [JsonPropertyName("locationKey")] + public string LocationKey { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the supplied path is within the session's allowed directories. -public sealed class PermissionPathsAllowedCheckResult +/// Folder trust check result. +[Experimental(Diagnostics.Experimental)] +public sealed class FolderTrustCheckResult { - /// Whether the path is within the session's allowed directories. - [JsonPropertyName("allowed")] - public bool Allowed { get; set; } + /// Whether the folder is trusted. + [JsonPropertyName("trusted")] + public bool Trusted { get; set; } } -/// Path to evaluate against the session's allowed directories. -internal sealed class PermissionPathsAllowedCheckParams +/// Folder path to check for trust. +[Experimental(Diagnostics.Experimental)] +internal sealed class FolderTrustCheckParams { - /// Path to check against the session's allowed directories. + /// Folder path to check. [JsonPropertyName("path")] public string Path { get; set; } = string.Empty; @@ -5227,18 +5799,20 @@ internal sealed class PermissionPathsAllowedCheckParams public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the supplied path is within the session's workspace directory. -public sealed class PermissionPathsWorkspaceCheckResult +/// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionsFolderTrustAddTrustedResult { - /// Whether the path is within the session workspace directory. - [JsonPropertyName("allowed")] - public bool Allowed { get; set; } + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } } -/// Path to evaluate against the session's workspace (primary) directory. -internal sealed class PermissionPathsWorkspaceCheckParams +/// Folder path to add to trusted folders. +[Experimental(Diagnostics.Experimental)] +internal sealed class FolderTrustAddParams { - /// Path to check against the session workspace directory. + /// Folder path to mark as trusted. [JsonPropertyName("path")] public string Path { get; set; } = string.Empty; @@ -5248,6 +5822,7 @@ internal sealed class PermissionPathsWorkspaceCheckParams } /// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsUrlsSetUnrestrictedModeResult { /// Whether the operation succeeded. @@ -5256,6 +5831,7 @@ public sealed class PermissionsUrlsSetUnrestrictedModeResult } /// Whether the URL-permission policy should run in unrestricted mode. +[Experimental(Diagnostics.Experimental)] internal sealed class PermissionUrlsSetUnrestrictedModeParams { /// Whether to allow access to all URLs without prompting. Toggles the runtime's URL-permission policy in place. @@ -5326,11 +5902,13 @@ public sealed class SessionMetadataSnapshotWorkspace /// Repository host type, if known. [JsonPropertyName("host_type")] - public SessionMetadataSnapshotWorkspaceHostType? HostType { get; set; } + public WorkspaceSummaryHostType? HostType { get; set; } /// Workspace identifier (1:1 with sessionId). + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] + [MinLength(1)] [JsonPropertyName("id")] - public Guid Id { get; set; } + public string Id { get; set; } = string.Empty; /// Display name for the session, if set. [JsonPropertyName("name")] @@ -5608,6 +6186,7 @@ internal sealed class MetadataRecomputeContextTokensRequest } /// Identifier of the spawned process, used to correlate streamed output and exit notifications. +[Experimental(Diagnostics.Experimental)] public sealed class ShellExecResult { /// Unique identifier for tracking streamed output. @@ -5616,6 +6195,7 @@ public sealed class ShellExecResult } /// Shell command to run, with optional working directory and timeout in milliseconds. +[Experimental(Diagnostics.Experimental)] internal sealed class ShellExecRequest { /// Shell command to execute. @@ -5637,6 +6217,7 @@ internal sealed class ShellExecRequest } /// Indicates whether the signal was delivered; false if the process was unknown or already exited. +[Experimental(Diagnostics.Experimental)] public sealed class ShellKillResult { /// Whether the signal was sent successfully. @@ -5645,6 +6226,7 @@ public sealed class ShellKillResult } /// Identifier of a process previously returned by "shell.exec" and the signal to send. +[Experimental(Diagnostics.Experimental)] internal sealed class ShellKillRequest { /// Process identifier returned by shell.exec. @@ -6588,13 +7170,13 @@ public ModelPickerCategory(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the lightweight value. + /// Lightweight model category optimized for faster, lower-cost interactions. public static ModelPickerCategory Lightweight { get; } = new("lightweight"); - /// Gets the versatile value. + /// Versatile model category suitable for a broad range of tasks. public static ModelPickerCategory Versatile { get; } = new("versatile"); - /// Gets the powerful value. + /// Powerful model category optimized for complex tasks. public static ModelPickerCategory Powerful { get; } = new("powerful"); /// Returns a value indicating whether two instances are equivalent. @@ -6653,16 +7235,16 @@ public ModelPickerPriceCategory(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the low value. + /// Lowest relative token cost tier. public static ModelPickerPriceCategory Low { get; } = new("low"); - /// Gets the medium value. + /// Medium relative token cost tier. public static ModelPickerPriceCategory Medium { get; } = new("medium"); - /// Gets the high value. + /// High relative token cost tier. public static ModelPickerPriceCategory High { get; } = new("high"); - /// Gets the very_high value. + /// Highest relative token cost tier. public static ModelPickerPriceCategory VeryHigh { get; } = new("very_high"); /// Returns a value indicating whether two instances are equivalent. @@ -6721,13 +7303,13 @@ public ModelPolicyState(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the enabled value. + /// The model is enabled by policy. public static ModelPolicyState Enabled { get; } = new("enabled"); - /// Gets the disabled value. + /// The model is disabled by policy. public static ModelPolicyState Disabled { get; } = new("disabled"); - /// Gets the unconfigured value. + /// No explicit policy is configured for the model. public static ModelPolicyState Unconfigured { get; } = new("unconfigured"); /// Returns a value indicating whether two instances are equivalent. @@ -6786,16 +7368,16 @@ public DiscoveredMcpServerType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the stdio value. + /// Server communicates over stdio with a local child process. public static DiscoveredMcpServerType Stdio { get; } = new("stdio"); - /// Gets the http value. + /// Server communicates over streamable HTTP. public static DiscoveredMcpServerType Http { get; } = new("http"); - /// Gets the sse value. + /// Server communicates over Server-Sent Events. public static DiscoveredMcpServerType Sse { get; } = new("sse"); - /// Gets the memory value. + /// Server is backed by an in-memory runtime implementation. public static DiscoveredMcpServerType Memory { get; } = new("memory"); /// Returns a value indicating whether two instances are equivalent. @@ -6854,10 +7436,10 @@ public SessionFsSetProviderConventions(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the windows value. + /// Paths use Windows path conventions. public static SessionFsSetProviderConventions Windows { get; } = new("windows"); - /// Gets the posix value. + /// Paths use POSIX path conventions. public static SessionFsSetProviderConventions Posix { get; } = new("posix"); /// Returns a value indicating whether two instances are equivalent. @@ -6917,10 +7499,10 @@ public ConnectedRemoteSessionMetadataKind(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the remote-session value. + /// Remote CLI session. public static ConnectedRemoteSessionMetadataKind RemoteSession { get; } = new("remote-session"); - /// Gets the coding-agent value. + /// GitHub Copilot coding agent session. public static ConnectedRemoteSessionMetadataKind CodingAgent { get; } = new("coding-agent"); /// Returns a value indicating whether two instances are equivalent. @@ -6980,10 +7562,10 @@ public SessionContextHostType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the github value. + /// Session repository is hosted on GitHub. public static SessionContextHostType Github { get; } = new("github"); - /// Gets the ado value. + /// Session repository is hosted on Azure DevOps. public static SessionContextHostType Ado { get; } = new("ado"); /// Returns a value indicating whether two instances are equivalent. @@ -7024,6 +7606,7 @@ public override void Write(Utf8JsonWriter writer, SessionContextHostType value, /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SendAgentMode : IEquatable @@ -7042,16 +7625,16 @@ public SendAgentMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the interactive value. + /// The agent is responding interactively to the user. public static SendAgentMode Interactive { get; } = new("interactive"); - /// Gets the plan value. + /// The agent is preparing a plan before making changes. public static SendAgentMode Plan { get; } = new("plan"); - /// Gets the autopilot value. + /// The agent is working autonomously toward task completion. public static SendAgentMode Autopilot { get; } = new("autopilot"); - /// Gets the shell value. + /// The agent is in shell-focused UI mode. public static SendAgentMode Shell { get; } = new("shell"); /// Returns a value indicating whether two instances are equivalent. @@ -7092,6 +7675,7 @@ public override void Write(Utf8JsonWriter writer, SendAgentMode value, JsonSeria /// Type of GitHub reference. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SendAttachmentGithubReferenceType : IEquatable @@ -7110,13 +7694,13 @@ public SendAttachmentGithubReferenceType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the issue value. + /// GitHub issue reference. public static SendAttachmentGithubReferenceType Issue { get; } = new("issue"); - /// Gets the pr value. + /// GitHub pull request reference. public static SendAttachmentGithubReferenceType Pr { get; } = new("pr"); - /// Gets the discussion value. + /// GitHub discussion reference. public static SendAttachmentGithubReferenceType Discussion { get; } = new("discussion"); /// Returns a value indicating whether two instances are equivalent. @@ -7157,6 +7741,7 @@ public override void Write(Utf8JsonWriter writer, SendAttachmentGithubReferenceT /// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SendMode : IEquatable @@ -7175,10 +7760,10 @@ public SendMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the enqueue value. + /// Append the message to the normal session queue. public static SendMode Enqueue { get; } = new("enqueue"); - /// Gets the immediate value. + /// Interject the message during the in-progress turn. public static SendMode Immediate { get; } = new("immediate"); /// Returns a value indicating whether two instances are equivalent. @@ -7219,6 +7804,7 @@ public override void Write(Utf8JsonWriter writer, SendMode value, JsonSerializer /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SessionLogLevel : IEquatable @@ -7237,13 +7823,13 @@ public SessionLogLevel(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the info value. + /// Informational message. public static SessionLogLevel Info { get; } = new("info"); - /// Gets the warning value. + /// Warning message that may require attention. public static SessionLogLevel Warning { get; } = new("warning"); - /// Gets the error value. + /// Error message describing a failure. public static SessionLogLevel Error { get; } = new("error"); /// Returns a value indicating whether two instances are equivalent. @@ -7284,6 +7870,7 @@ public override void Write(Utf8JsonWriter writer, SessionLogLevel value, JsonSer /// Authentication type. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct AuthInfoType : IEquatable @@ -7302,25 +7889,25 @@ public AuthInfoType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the hmac value. + /// Authentication provided by a GitHub App HMAC credential. public static AuthInfoType Hmac { get; } = new("hmac"); - /// Gets the env value. + /// Authentication resolved from environment-provided credentials. public static AuthInfoType Env { get; } = new("env"); - /// Gets the user value. + /// Authentication from an interactive user sign-in. public static AuthInfoType User { get; } = new("user"); - /// Gets the gh-cli value. + /// Authentication delegated to the GitHub CLI. public static AuthInfoType GhCli { get; } = new("gh-cli"); - /// Gets the api-key value. + /// Authentication from an API key credential. public static AuthInfoType ApiKey { get; } = new("api-key"); - /// Gets the token value. + /// Authentication from a GitHub token. public static AuthInfoType Token { get; } = new("token"); - /// Gets the copilot-api-token value. + /// Authentication from a Copilot API token. public static AuthInfoType CopilotApiToken { get; } = new("copilot-api-token"); /// Returns a value indicating whether two instances are equivalent. @@ -7360,42 +7947,43 @@ public override void Write(Utf8JsonWriter writer, AuthInfoType value, JsonSerial } -/// Defines the allowed values. +/// Allowed values for the `WorkspacesWorkspaceDetailsHostType` enumeration. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] -public readonly struct WorkspacesGetWorkspaceResultWorkspaceHostType : IEquatable +public readonly struct WorkspacesWorkspaceDetailsHostType : IEquatable { private readonly string? _value; - /// Initializes a new instance of the struct. - /// The value to associate with this . + /// Initializes a new instance of the struct. + /// The value to associate with this . [JsonConstructor] - public WorkspacesGetWorkspaceResultWorkspaceHostType(string value) + public WorkspacesWorkspaceDetailsHostType(string value) { ArgumentException.ThrowIfNullOrWhiteSpace(value); _value = value; } - /// Gets the value associated with this . + /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the github value. - public static WorkspacesGetWorkspaceResultWorkspaceHostType Github { get; } = new("github"); + /// Workspace repository is hosted on GitHub. + public static WorkspacesWorkspaceDetailsHostType Github { get; } = new("github"); - /// Gets the ado value. - public static WorkspacesGetWorkspaceResultWorkspaceHostType Ado { get; } = new("ado"); + /// Workspace repository is hosted on Azure DevOps. + public static WorkspacesWorkspaceDetailsHostType Ado { get; } = new("ado"); - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => left.Equals(right); + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(WorkspacesWorkspaceDetailsHostType left, WorkspacesWorkspaceDetailsHostType right) => left.Equals(right); - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => !(left == right); + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(WorkspacesWorkspaceDetailsHostType left, WorkspacesWorkspaceDetailsHostType right) => !(left == right); /// - public override bool Equals(object? obj) => obj is WorkspacesGetWorkspaceResultWorkspaceHostType other && Equals(other); + public override bool Equals(object? obj) => obj is WorkspacesWorkspaceDetailsHostType other && Equals(other); /// - public bool Equals(WorkspacesGetWorkspaceResultWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + public bool Equals(WorkspacesWorkspaceDetailsHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); /// public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); @@ -7403,26 +7991,27 @@ public WorkspacesGetWorkspaceResultWorkspaceHostType(string value) /// public override string ToString() => Value; - /// Provides a for serializing instances. + /// Provides a for serializing instances. [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter + public sealed class Converter : JsonConverter { /// - public override WorkspacesGetWorkspaceResultWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override WorkspacesWorkspaceDetailsHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// - public override void Write(Utf8JsonWriter writer, WorkspacesGetWorkspaceResultWorkspaceHostType value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, WorkspacesWorkspaceDetailsHostType value, JsonSerializerOptions options) { - GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesWorkspaceDetailsHostType)); } } } /// Where this source lives — used for UI grouping. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct InstructionsSourcesLocation : IEquatable @@ -7441,16 +8030,16 @@ public InstructionsSourcesLocation(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the user value. + /// Instructions live in user-level configuration. public static InstructionsSourcesLocation User { get; } = new("user"); - /// Gets the repository value. + /// Instructions live in repository-level configuration. public static InstructionsSourcesLocation Repository { get; } = new("repository"); - /// Gets the working-directory value. + /// Instructions live under the current working directory. public static InstructionsSourcesLocation WorkingDirectory { get; } = new("working-directory"); - /// Gets the plugin value. + /// Instructions live in plugin-provided configuration. public static InstructionsSourcesLocation Plugin { get; } = new("plugin"); /// Returns a value indicating whether two instances are equivalent. @@ -7491,6 +8080,7 @@ public override void Write(Utf8JsonWriter writer, InstructionsSourcesLocation va /// Category of instruction source — used for merge logic. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct InstructionsSourcesType : IEquatable @@ -7509,25 +8099,25 @@ public InstructionsSourcesType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the home value. + /// Instructions loaded from the user's home configuration. public static InstructionsSourcesType Home { get; } = new("home"); - /// Gets the repo value. + /// Instructions loaded from repository-scoped files. public static InstructionsSourcesType Repo { get; } = new("repo"); - /// Gets the model value. + /// Instructions loaded from model-specific files. public static InstructionsSourcesType Model { get; } = new("model"); - /// Gets the vscode value. + /// Instructions loaded from VS Code instruction files. public static InstructionsSourcesType Vscode { get; } = new("vscode"); - /// Gets the nested-agents value. + /// Instructions discovered from nested agent files. public static InstructionsSourcesType NestedAgents { get; } = new("nested-agents"); - /// Gets the child-instructions value. + /// Instructions inherited from child instruction files. public static InstructionsSourcesType ChildInstructions { get; } = new("child-instructions"); - /// Gets the plugin value. + /// Instructions supplied by an installed plugin. public static InstructionsSourcesType Plugin { get; } = new("plugin"); /// Returns a value indicating whether two instances are equivalent. @@ -7587,22 +8177,22 @@ public AgentInfoSource(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the user value. + /// Agent loaded from the user's personal agent configuration. public static AgentInfoSource User { get; } = new("user"); - /// Gets the project value. + /// Agent loaded from the current project's repository configuration. public static AgentInfoSource Project { get; } = new("project"); - /// Gets the inherited value. + /// Agent inherited from a parent project or workspace. public static AgentInfoSource Inherited { get; } = new("inherited"); - /// Gets the remote value. + /// Agent provided by a remote runtime or service. public static AgentInfoSource Remote { get; } = new("remote"); - /// Gets the plugin value. + /// Agent contributed by an installed plugin. public static AgentInfoSource Plugin { get; } = new("plugin"); - /// Gets the builtin value. + /// Agent built into the Copilot runtime. public static AgentInfoSource Builtin { get; } = new("builtin"); /// Returns a value indicating whether two instances are equivalent. @@ -7662,10 +8252,10 @@ public TaskExecutionMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the sync value. + /// The task was started with synchronous waiting. public static TaskExecutionMode Sync { get; } = new("sync"); - /// Gets the background value. + /// The task is managed in the background. public static TaskExecutionMode Background { get; } = new("background"); /// Returns a value indicating whether two instances are equivalent. @@ -7725,19 +8315,19 @@ public TaskStatus(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the running value. + /// The task is actively executing. public static TaskStatus Running { get; } = new("running"); - /// Gets the idle value. + /// The task is waiting for additional input. public static TaskStatus Idle { get; } = new("idle"); - /// Gets the completed value. + /// The task finished successfully. public static TaskStatus Completed { get; } = new("completed"); - /// Gets the failed value. + /// The task finished with an error. public static TaskStatus Failed { get; } = new("failed"); - /// Gets the cancelled value. + /// The task was cancelled before completion. public static TaskStatus Cancelled { get; } = new("cancelled"); /// Returns a value indicating whether two instances are equivalent. @@ -7797,10 +8387,10 @@ public TaskShellInfoAttachmentMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the attached value. + /// The shell runs in a managed PTY session. public static TaskShellInfoAttachmentMode Attached { get; } = new("attached"); - /// Gets the detached value. + /// The shell runs as an independent background process. public static TaskShellInfoAttachmentMode Detached { get; } = new("detached"); /// Returns a value indicating whether two instances are equivalent. @@ -7860,13 +8450,13 @@ public McpSamplingExecutionAction(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the success value. + /// The sampling inference completed and produced a result. public static McpSamplingExecutionAction Success { get; } = new("success"); - /// Gets the failure value. + /// The sampling inference failed or was rejected. public static McpSamplingExecutionAction Failure { get; } = new("failure"); - /// Gets the cancelled value. + /// The sampling inference was cancelled before completion. public static McpSamplingExecutionAction Cancelled { get; } = new("cancelled"); /// Returns a value indicating whether two instances are equivalent. @@ -7926,10 +8516,10 @@ public McpSetEnvValueModeDetails(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the direct value. + /// Treat MCP server environment values as literal strings. public static McpSetEnvValueModeDetails Direct { get; } = new("direct"); - /// Gets the indirect value. + /// Treat MCP server environment values as host-side references to resolve before launch. public static McpSetEnvValueModeDetails Indirect { get; } = new("indirect"); /// Returns a value indicating whether two instances are equivalent. @@ -7989,10 +8579,10 @@ public OptionsUpdateEnvValueMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the direct value. + /// Pass MCP server environment values as literal strings. public static OptionsUpdateEnvValueMode Direct { get; } = new("direct"); - /// Gets the indirect value. + /// Resolve MCP server environment values from host-side references. public static OptionsUpdateEnvValueMode Indirect { get; } = new("indirect"); /// Returns a value indicating whether two instances are equivalent. @@ -8052,10 +8642,10 @@ public ExtensionSource(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the project value. + /// Extension discovered from the current project's .github/extensions directory. public static ExtensionSource Project { get; } = new("project"); - /// Gets the user value. + /// Extension discovered from the user's ~/.copilot/extensions directory. public static ExtensionSource User { get; } = new("user"); /// Returns a value indicating whether two instances are equivalent. @@ -8115,16 +8705,16 @@ public ExtensionStatus(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the running value. + /// The extension process is running. public static ExtensionStatus Running { get; } = new("running"); - /// Gets the disabled value. + /// The extension is installed but disabled. public static ExtensionStatus Disabled { get; } = new("disabled"); - /// Gets the failed value. + /// The extension failed to start or crashed. public static ExtensionStatus Failed { get; } = new("failed"); - /// Gets the starting value. + /// The extension process is starting. public static ExtensionStatus Starting { get; } = new("starting"); /// Returns a value indicating whether two instances are equivalent. @@ -8165,6 +8755,7 @@ public override void Write(Utf8JsonWriter writer, ExtensionStatus value, JsonSer /// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SlashCommandInputCompletion : IEquatable @@ -8183,7 +8774,7 @@ public SlashCommandInputCompletion(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the directory value. + /// Input should complete filesystem directories. public static SlashCommandInputCompletion Directory { get; } = new("directory"); /// Returns a value indicating whether two instances are equivalent. @@ -8224,6 +8815,7 @@ public override void Write(Utf8JsonWriter writer, SlashCommandInputCompletion va /// Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct SlashCommandKind : IEquatable @@ -8242,13 +8834,13 @@ public SlashCommandKind(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the builtin value. + /// Command implemented by the runtime. public static SlashCommandKind Builtin { get; } = new("builtin"); - /// Gets the skill value. + /// Command backed by a skill. public static SlashCommandKind Skill { get; } = new("skill"); - /// Gets the client value. + /// Command registered by an SDK client or extension. public static SlashCommandKind Client { get; } = new("client"); /// Returns a value indicating whether two instances are equivalent. @@ -8289,6 +8881,7 @@ public override void Write(Utf8JsonWriter writer, SlashCommandKind value, JsonSe /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct UIElicitationResponseAction : IEquatable @@ -8307,13 +8900,13 @@ public UIElicitationResponseAction(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the accept value. + /// The user submitted the requested form values. public static UIElicitationResponseAction Accept { get; } = new("accept"); - /// Gets the decline value. + /// The user explicitly declined to provide the requested input. public static UIElicitationResponseAction Decline { get; } = new("decline"); - /// Gets the cancel value. + /// The user dismissed the elicitation request. public static UIElicitationResponseAction Cancel { get; } = new("cancel"); /// Returns a value indicating whether two instances are equivalent. @@ -8354,6 +8947,7 @@ public override void Write(Utf8JsonWriter writer, UIElicitationResponseAction va /// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct UIAutoModeSwitchResponse : IEquatable @@ -8372,13 +8966,13 @@ public UIAutoModeSwitchResponse(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the yes value. + /// Allow the automatic mode switch for this turn. public static UIAutoModeSwitchResponse Yes { get; } = new("yes"); - /// Gets the yes_always value. + /// Allow this mode switch and persist the preference. public static UIAutoModeSwitchResponse YesAlways { get; } = new("yes_always"); - /// Gets the no value. + /// Decline the automatic mode switch. public static UIAutoModeSwitchResponse No { get; } = new("no"); /// Returns a value indicating whether two instances are equivalent. @@ -8419,6 +9013,7 @@ public override void Write(Utf8JsonWriter writer, UIAutoModeSwitchResponse value /// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct UIExitPlanModeAction : IEquatable @@ -8437,16 +9032,16 @@ public UIExitPlanModeAction(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the exit_only value. + /// Exit plan mode without starting implementation. public static UIExitPlanModeAction ExitOnly { get; } = new("exit_only"); - /// Gets the interactive value. + /// Exit plan mode and continue interactively. public static UIExitPlanModeAction Interactive { get; } = new("interactive"); - /// Gets the autopilot value. + /// Exit plan mode and continue in autopilot mode. public static UIExitPlanModeAction Autopilot { get; } = new("autopilot"); - /// Gets the autopilot_fleet value. + /// Exit plan mode and continue in autopilot mode with parallel subagent execution. public static UIExitPlanModeAction AutopilotFleet { get; } = new("autopilot_fleet"); /// Returns a value indicating whether two instances are equivalent. @@ -8487,6 +9082,7 @@ public override void Write(Utf8JsonWriter writer, UIExitPlanModeAction value, Js /// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct PermissionsConfigureAdditionalContentExclusionPolicyScope : IEquatable @@ -8505,10 +9101,10 @@ public PermissionsConfigureAdditionalContentExclusionPolicyScope(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the repo value. + /// The content exclusion policy applies to the current repository. public static PermissionsConfigureAdditionalContentExclusionPolicyScope Repo { get; } = new("repo"); - /// Gets the all value. + /// The content exclusion policy applies across all repositories. public static PermissionsConfigureAdditionalContentExclusionPolicyScope All { get; } = new("all"); /// Returns a value indicating whether two instances are equivalent. @@ -8549,6 +9145,7 @@ public override void Write(Utf8JsonWriter writer, PermissionsConfigureAdditional /// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct PermissionsSetApproveAllSource : IEquatable @@ -8567,16 +9164,16 @@ public PermissionsSetApproveAllSource(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the cli_flag value. + /// Allow-all was enabled from a CLI command-line flag. public static PermissionsSetApproveAllSource CliFlag { get; } = new("cli_flag"); - /// Gets the slash_command value. + /// Allow-all was enabled by a slash command. public static PermissionsSetApproveAllSource SlashCommand { get; } = new("slash_command"); - /// Gets the autopilot_confirmation value. + /// Allow-all was enabled by confirming autopilot behavior. public static PermissionsSetApproveAllSource AutopilotConfirmation { get; } = new("autopilot_confirmation"); - /// Gets the rpc value. + /// Allow-all was enabled through an RPC caller. public static PermissionsSetApproveAllSource Rpc { get; } = new("rpc"); /// Returns a value indicating whether two instances are equivalent. @@ -8617,6 +9214,7 @@ public override void Write(Utf8JsonWriter writer, PermissionsSetApproveAllSource /// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct PermissionsModifyRulesScope : IEquatable @@ -8635,10 +9233,10 @@ public PermissionsModifyRulesScope(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the session value. + /// Apply the rule change only to this session. public static PermissionsModifyRulesScope Session { get; } = new("session"); - /// Gets the location value. + /// Persist the rule change for this project location. public static PermissionsModifyRulesScope Location { get; } = new("location"); /// Returns a value indicating whether two instances are equivalent. @@ -8678,6 +9276,69 @@ public override void Write(Utf8JsonWriter writer, PermissionsModifyRulesScope va } +/// Whether the location is a git repo or directory. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct PermissionLocationType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public PermissionLocationType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// The permission location is persisted at the git repository root. + public static PermissionLocationType Repo { get; } = new("repo"); + + /// The permission location is persisted at the working directory. + public static PermissionLocationType Dir { get; } = new("dir"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(PermissionLocationType left, PermissionLocationType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(PermissionLocationType left, PermissionLocationType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is PermissionLocationType other && Equals(other); + + /// + public bool Equals(PermissionLocationType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override PermissionLocationType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, PermissionLocationType value, JsonSerializerOptions options) + { + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionLocationType)); + } + } +} + + /// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot'). [Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] @@ -8698,13 +9359,13 @@ public MetadataSnapshotCurrentMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the interactive value. + /// The agent is responding interactively to the user. public static MetadataSnapshotCurrentMode Interactive { get; } = new("interactive"); - /// Gets the plan value. + /// The agent is preparing a plan before making changes. public static MetadataSnapshotCurrentMode Plan { get; } = new("plan"); - /// Gets the autopilot value. + /// The agent is working autonomously toward task completion. public static MetadataSnapshotCurrentMode Autopilot { get; } = new("autopilot"); /// Returns a value indicating whether two instances are equivalent. @@ -8764,10 +9425,10 @@ public MetadataSnapshotRemoteMetadataTaskType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the cca value. + /// Remote task originated from Copilot Coding Agent. public static MetadataSnapshotRemoteMetadataTaskType Cca { get; } = new("cca"); - /// Gets the cli value. + /// Remote task originated from a CLI remote-session invocation. public static MetadataSnapshotRemoteMetadataTaskType Cli { get; } = new("cli"); /// Returns a value indicating whether two instances are equivalent. @@ -8808,41 +9469,42 @@ public override void Write(Utf8JsonWriter writer, MetadataSnapshotRemoteMetadata /// Repository host type, if known. +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] -public readonly struct SessionMetadataSnapshotWorkspaceHostType : IEquatable +public readonly struct WorkspaceSummaryHostType : IEquatable { private readonly string? _value; - /// Initializes a new instance of the struct. - /// The value to associate with this . + /// Initializes a new instance of the struct. + /// The value to associate with this . [JsonConstructor] - public SessionMetadataSnapshotWorkspaceHostType(string value) + public WorkspaceSummaryHostType(string value) { ArgumentException.ThrowIfNullOrWhiteSpace(value); _value = value; } - /// Gets the value associated with this . + /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the github value. - public static SessionMetadataSnapshotWorkspaceHostType Github { get; } = new("github"); + /// Workspace summary repository is hosted on GitHub. + public static WorkspaceSummaryHostType Github { get; } = new("github"); - /// Gets the ado value. - public static SessionMetadataSnapshotWorkspaceHostType Ado { get; } = new("ado"); + /// Workspace summary repository is hosted on Azure DevOps. + public static WorkspaceSummaryHostType Ado { get; } = new("ado"); - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SessionMetadataSnapshotWorkspaceHostType left, SessionMetadataSnapshotWorkspaceHostType right) => left.Equals(right); + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(WorkspaceSummaryHostType left, WorkspaceSummaryHostType right) => left.Equals(right); - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SessionMetadataSnapshotWorkspaceHostType left, SessionMetadataSnapshotWorkspaceHostType right) => !(left == right); + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(WorkspaceSummaryHostType left, WorkspaceSummaryHostType right) => !(left == right); /// - public override bool Equals(object? obj) => obj is SessionMetadataSnapshotWorkspaceHostType other && Equals(other); + public override bool Equals(object? obj) => obj is WorkspaceSummaryHostType other && Equals(other); /// - public bool Equals(SessionMetadataSnapshotWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + public bool Equals(WorkspaceSummaryHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); /// public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); @@ -8850,20 +9512,20 @@ public SessionMetadataSnapshotWorkspaceHostType(string value) /// public override string ToString() => Value; - /// Provides a for serializing instances. + /// Provides a for serializing instances. [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter + public sealed class Converter : JsonConverter { /// - public override SessionMetadataSnapshotWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override WorkspaceSummaryHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); } /// - public override void Write(Utf8JsonWriter writer, SessionMetadataSnapshotWorkspaceHostType value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, WorkspaceSummaryHostType value, JsonSerializerOptions options) { - GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); + GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspaceSummaryHostType)); } } } @@ -8889,10 +9551,10 @@ public SessionWorkingDirectoryContextHostType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the github value. + /// The working directory repository is hosted on GitHub. public static SessionWorkingDirectoryContextHostType Github { get; } = new("github"); - /// Gets the ado value. + /// The working directory repository is hosted on Azure DevOps. public static SessionWorkingDirectoryContextHostType Ado { get; } = new("ado"); /// Returns a value indicating whether two instances are equivalent. @@ -8933,6 +9595,7 @@ public override void Write(Utf8JsonWriter writer, SessionWorkingDirectoryContext /// Signal to send (default: SIGTERM). +[Experimental(Diagnostics.Experimental)] [JsonConverter(typeof(Converter))] [DebuggerDisplay("{Value,nq}")] public readonly struct ShellKillSignal : IEquatable @@ -8951,13 +9614,13 @@ public ShellKillSignal(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the SIGTERM value. + /// Request graceful process termination. public static ShellKillSignal SIGTERM { get; } = new("SIGTERM"); - /// Gets the SIGKILL value. + /// Forcefully terminate the process. public static ShellKillSignal SIGKILL { get; } = new("SIGKILL"); - /// Gets the SIGINT value. + /// Send an interrupt signal to the process. public static ShellKillSignal SIGINT { get; } = new("SIGINT"); /// Returns a value indicating whether two instances are equivalent. @@ -9017,10 +9680,10 @@ public QueuePendingItemsKind(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the message value. + /// A queued user message. public static QueuePendingItemsKind Message { get; } = new("message"); - /// Gets the command value. + /// A queued slash command or model-change command. public static QueuePendingItemsKind Command { get; } = new("command"); /// Returns a value indicating whether two instances are equivalent. @@ -9080,10 +9743,10 @@ public EventsCursorStatus(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the ok value. + /// The cursor was applied successfully. public static EventsCursorStatus Ok { get; } = new("ok"); - /// Gets the expired value. + /// The cursor referred to history that is no longer available. public static EventsCursorStatus Expired { get; } = new("expired"); /// Returns a value indicating whether two instances are equivalent. @@ -9143,10 +9806,10 @@ public EventsAgentScope(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the primary value. + /// Return main-agent events and typed subagent lifecycle events. public static EventsAgentScope Primary { get; } = new("primary"); - /// Gets the all value. + /// Return events from all agents. public static EventsAgentScope All { get; } = new("all"); /// Returns a value indicating whether two instances are equivalent. @@ -9206,13 +9869,13 @@ public RemoteSessionMode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the off value. + /// Disable remote session export and steering. public static RemoteSessionMode Off { get; } = new("off"); - /// Gets the export value. + /// Export session events to GitHub without enabling remote steering. public static RemoteSessionMode Export { get; } = new("export"); - /// Gets the on value. + /// Enable both remote session export and remote steering. public static RemoteSessionMode On { get; } = new("on"); /// Returns a value indicating whether two instances are equivalent. @@ -9271,10 +9934,10 @@ public SessionFsErrorCode(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the ENOENT value. + /// The requested path does not exist. public static SessionFsErrorCode ENOENT { get; } = new("ENOENT"); - /// Gets the UNKNOWN value. + /// The filesystem operation failed for an unspecified reason. public static SessionFsErrorCode UNKNOWN { get; } = new("UNKNOWN"); /// Returns a value indicating whether two instances are equivalent. @@ -9333,10 +9996,10 @@ public SessionFsReaddirWithTypesEntryType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the file value. + /// The entry is a file. public static SessionFsReaddirWithTypesEntryType File { get; } = new("file"); - /// Gets the directory value. + /// The entry is a directory. public static SessionFsReaddirWithTypesEntryType Directory { get; } = new("directory"); /// Returns a value indicating whether two instances are equivalent. @@ -9395,13 +10058,13 @@ public SessionFsSqliteQueryType(string value) /// Gets the value associated with this . public string Value => _value ?? string.Empty; - /// Gets the exec value. + /// Execute DDL or multi-statement SQL without returning rows. public static SessionFsSqliteQueryType Exec { get; } = new("exec"); - /// Gets the query value. + /// Execute a SELECT-style query and return rows. public static SessionFsSqliteQueryType Query { get; } = new("query"); - /// Gets the run value. + /// Execute INSERT, UPDATE, or DELETE SQL and return affected-row metadata. public static SessionFsSqliteQueryType Run { get; } = new("run"); /// Returns a value indicating whether two instances are equivalent. @@ -9801,7 +10464,7 @@ public async Task ConnectAsync(string sessionId, /// Optional filter applied to the returned sessions. /// The to monitor for cancellation requests. The default is . /// Persisted sessions matching the filter, ordered most-recently-modified first. - public async Task ListAsync(long? metadataLimit = null, SessionsListRequestFilter? filter = null, CancellationToken cancellationToken = default) + public async Task ListAsync(long? metadataLimit = null, SessionListFilter? filter = null, CancellationToken cancellationToken = default) { var request = new SessionsListRequest { MetadataLimit = metadataLimit, Filter = filter }; return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.list", [request], cancellationToken); @@ -10184,6 +10847,7 @@ internal SessionRpc(CopilotSession session) /// Suspends the session while preserving persisted state for later resume. /// The to monitor for cancellation requests. The default is . + [Experimental(Diagnostics.Experimental)] public async Task SuspendAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -10208,6 +10872,7 @@ public async Task SuspendAsync(CancellationToken cancellationToken = default) /// If true, await completion of the agentic loop for this message before returning. Defaults to false (fire-and-forget). When true, the result still contains the same `messageId`; the caller can rely on the agent having processed the message before the call resolves. /// The to monitor for cancellation requests. The default is . /// Result of sending a user message. + [Experimental(Diagnostics.Experimental)] public async Task SendAsync(string prompt, string? displayPrompt = null, IList? attachments = null, SendMode? mode = null, bool? prepend = null, bool? billable = null, string? requiredTool = null, object? source = null, SendAgentMode? agentMode = null, IDictionary? requestHeaders = null, string? traceparent = null, string? tracestate = null, bool? wait = null, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(prompt); @@ -10221,6 +10886,7 @@ public async Task SendAsync(string prompt, string? displayPrompt = n /// Finite reason code describing why the current turn was aborted. /// The to monitor for cancellation requests. The default is . /// Result of aborting the current turn. + [Experimental(Diagnostics.Experimental)] public async Task AbortAsync(AbortReason? reason = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -10233,6 +10899,7 @@ public async Task AbortAsync(AbortReason? reason = null, Cancellati /// Why the session is being shut down. Defaults to "routine" when omitted. /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. /// The to monitor for cancellation requests. The default is . + [Experimental(Diagnostics.Experimental)] public async Task ShutdownAsync(ShutdownType? type = null, string? reason = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -10250,6 +10917,7 @@ public async Task ShutdownAsync(ShutdownType? type = null, string? reason = null /// Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. /// The to monitor for cancellation requests. The default is . /// Identifier of the session event that was emitted for the log message. + [Experimental(Diagnostics.Experimental)] public async Task LogAsync(string message, SessionLogLevel? level = null, string? type = null, bool? ephemeral = null, string? url = null, string? tip = null, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(message); @@ -10261,6 +10929,7 @@ public async Task LogAsync(string message, SessionLogLevel? level = n } /// Provides session-scoped Auth APIs. +[Experimental(Diagnostics.Experimental)] public sealed class AuthApi { private readonly CopilotSession _session; @@ -10295,6 +10964,7 @@ public async Task SetCredentialsAsync(AuthInfo? cre } /// Provides session-scoped Model APIs. +[Experimental(Diagnostics.Experimental)] public sealed class ModelApi { private readonly CopilotSession _session; @@ -10346,6 +11016,7 @@ public async Task SetReasoningEffortAsync(string } /// Provides session-scoped Mode APIs. +[Experimental(Diagnostics.Experimental)] public sealed class ModeApi { private readonly CopilotSession _session; @@ -10379,6 +11050,7 @@ public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken } /// Provides session-scoped Name APIs. +[Experimental(Diagnostics.Experimental)] public sealed class NameApi { private readonly CopilotSession _session; @@ -10426,6 +11098,7 @@ public async Task SetAutoAsync(string summary, CancellationTo } /// Provides session-scoped Plan APIs. +[Experimental(Diagnostics.Experimental)] public sealed class PlanApi { private readonly CopilotSession _session; @@ -10470,6 +11143,7 @@ public async Task DeleteAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Workspaces APIs. +[Experimental(Diagnostics.Experimental)] public sealed class WorkspacesApi { private readonly CopilotSession _session; @@ -10566,6 +11240,7 @@ public async Task SaveLargePasteAsync(string con } /// Provides session-scoped Instructions APIs. +[Experimental(Diagnostics.Experimental)] public sealed class InstructionsApi { private readonly CopilotSession _session; @@ -11223,6 +11898,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Tools APIs. +[Experimental(Diagnostics.Experimental)] public sealed class ToolsApi { private readonly CopilotSession _session; @@ -11260,6 +11936,7 @@ public async Task InitializeAndValidateAsync(C } /// Provides session-scoped Commands APIs. +[Experimental(Diagnostics.Experimental)] public sealed class CommandsApi { private readonly CopilotSession _session; @@ -11378,6 +12055,7 @@ public async Task SetFeatureOverridesAsync(IDictionary features, } /// Provides session-scoped Ui APIs. +[Experimental(Diagnostics.Experimental)] public sealed class UiApi { private readonly CopilotSession _session; @@ -11501,6 +12179,7 @@ public async Task UnregisterDirec } /// Provides session-scoped Permissions APIs. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsApi { private readonly CopilotSession _session; @@ -11623,6 +12302,18 @@ public async Task NotifyPromptShownAsync(str Interlocked.CompareExchange(ref field, new(_session), null) ?? field; + /// Locations APIs. + public PermissionsLocationsApi Locations => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// FolderTrust APIs. + public PermissionsFolderTrustApi FolderTrust => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + /// Urls APIs. public PermissionsUrlsApi Urls => field ?? @@ -11631,6 +12322,7 @@ public async Task NotifyPromptShownAsync(str } /// Provides session-scoped PermissionsPaths APIs. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsPathsApi { private readonly CopilotSession _session; @@ -11704,7 +12396,99 @@ public async Task IsPathWithinWorkspaceAsyn } } +/// Provides session-scoped PermissionsLocations APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionsLocationsApi +{ + private readonly CopilotSession _session; + + internal PermissionsLocationsApi(CopilotSession session) + { + _session = session; + } + + /// Resolves the permission location key and type for a working directory. + /// Working directory whose permission location should be resolved. + /// The to monitor for cancellation requests. The default is . + /// Resolved location-permissions key and type. + public async Task ResolveAsync(string workingDirectory, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(workingDirectory); + _session.ThrowIfDisposed(); + + var request = new PermissionLocationResolveParams { SessionId = _session.SessionId, WorkingDirectory = workingDirectory }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.locations.resolve", [request], cancellationToken); + } + + /// Applies persisted location-scoped tool approvals and allowed directories for a working directory to this session's permission service. + /// Working directory whose persisted location permissions should be applied. + /// The to monitor for cancellation requests. The default is . + /// Summary of persisted location permissions applied to the session. + public async Task ApplyAsync(string workingDirectory, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(workingDirectory); + _session.ThrowIfDisposed(); + + var request = new PermissionLocationApplyParams { SessionId = _session.SessionId, WorkingDirectory = workingDirectory }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.locations.apply", [request], cancellationToken); + } + + /// Persists a tool approval for a permission location and applies its rules to this session's live permission service. + /// Location key (git root or cwd) to persist the approval to. + /// Tool approval to persist and apply. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the operation succeeded. + public async Task AddToolApprovalAsync(string locationKey, PermissionsLocationsAddToolApprovalDetails approval, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(locationKey); + ArgumentNullException.ThrowIfNull(approval); + _session.ThrowIfDisposed(); + + var request = new PermissionLocationAddToolApprovalParams { SessionId = _session.SessionId, LocationKey = locationKey, Approval = approval }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.locations.addToolApproval", [request], cancellationToken); + } +} + +/// Provides session-scoped PermissionsFolderTrust APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class PermissionsFolderTrustApi +{ + private readonly CopilotSession _session; + + internal PermissionsFolderTrustApi(CopilotSession session) + { + _session = session; + } + + /// Reports whether a folder is trusted according to the user's folder trust state. + /// Folder path to check. + /// The to monitor for cancellation requests. The default is . + /// Folder trust check result. + public async Task IsTrustedAsync(string path, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(path); + _session.ThrowIfDisposed(); + + var request = new FolderTrustCheckParams { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.folderTrust.isTrusted", [request], cancellationToken); + } + + /// Adds a folder to the user's trusted folders list. + /// Folder path to mark as trusted. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the operation succeeded. + public async Task AddTrustedAsync(string path, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(path); + _session.ThrowIfDisposed(); + + var request = new FolderTrustAddParams { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.folderTrust.addTrusted", [request], cancellationToken); + } +} + /// Provides session-scoped PermissionsUrls APIs. +[Experimental(Diagnostics.Experimental)] public sealed class PermissionsUrlsApi { private readonly CopilotSession _session; @@ -11815,6 +12599,7 @@ public async Task RecomputeContextTokensAs } /// Provides session-scoped Shell APIs. +[Experimental(Diagnostics.Experimental)] public sealed class ShellApi { private readonly CopilotSession _session; @@ -12569,6 +13354,9 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func Date: Thu, 21 May 2026 10:28:52 +0100 Subject: [PATCH 40/40] Test: make Should_Get_Null_Last_Session_Id resilient to test order The runtime tracks 'last session id' as a persistent value (it survives session deletion), so this test fails if any other test in the class has run first. Latent on main because xUnit happened to run it first; exposed on this branch by the namespace rename which changes the fully-qualified type name and therefore the discovered test order. Cleaning up any pre-existing sessions before reading the value lets the test pass regardless of order. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/E2E/ClientSessionManagementE2ETests.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dotnet/test/E2E/ClientSessionManagementE2ETests.cs b/dotnet/test/E2E/ClientSessionManagementE2ETests.cs index f6b126ce7..961b0e028 100644 --- a/dotnet/test/E2E/ClientSessionManagementE2ETests.cs +++ b/dotnet/test/E2E/ClientSessionManagementE2ETests.cs @@ -47,6 +47,14 @@ public async Task Should_Get_Null_Last_Session_Id_Before_Any_Sessions_Exist() { await Client.StartAsync(); + // Other tests in this class create sessions, and xUnit doesn't guarantee + // test execution order. Clear any leftover sessions so this test sees a + // genuinely empty state regardless of order. + foreach (var existing in await Client.ListSessionsAsync()) + { + await Client.DeleteSessionAsync(existing.SessionId); + } + var result = await Client.GetLastSessionIdAsync(); Assert.Null(result);