diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 6962a977..c1dc311d 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -49,7 +49,7 @@ namespace GitHub.Copilot.SDK; /// await session.SendAsync(new MessageOptions { Prompt = "Hello!" }); /// /// -public class CopilotClient : IDisposable, IAsyncDisposable +public partial class CopilotClient : IDisposable, IAsyncDisposable { private readonly ConcurrentDictionary _sessions = new(); private readonly CopilotClientOptions _options; @@ -461,7 +461,7 @@ public async Task PingAsync(string? message = null, CancellationTo var connection = await EnsureConnectedAsync(cancellationToken); return await connection.Rpc.InvokeWithCancellationAsync( - "ping", [new { message }], cancellationToken); + "ping", [new PingRequest { Message = message }], cancellationToken); } /// @@ -554,7 +554,7 @@ public async Task DeleteSessionAsync(string sessionId, CancellationToken cancell var connection = await EnsureConnectedAsync(cancellationToken); var response = await connection.Rpc.InvokeWithCancellationAsync( - "session.delete", [new { sessionId }], cancellationToken); + "session.delete", [new DeleteSessionRequest(sessionId)], cancellationToken); if (!response.Success) { @@ -604,7 +604,7 @@ private async Task VerifyProtocolVersionAsync(Connection connection, Cancellatio { var expectedVersion = SdkProtocolVersion.GetVersion(); var pingResponse = await connection.Rpc.InvokeWithCancellationAsync( - "ping", [new { message = (string?)null }], cancellationToken); + "ping", [new PingRequest()], cancellationToken); if (!pingResponse.ProtocolVersion.HasValue) { @@ -754,15 +754,30 @@ private async Task ConnectToServerAsync(Process? cliProcess, string? outputStream = networkStream; } - var rpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, CreateFormatter())); - rpc.AddLocalRpcTarget(new RpcHandler(this)); + var rpc = new JsonRpc(new HeaderDelimitedMessageHandler( + outputStream, + inputStream, + CreateSystemTextJsonFormatter())) + { + TraceSource = new LoggerTraceSource(_logger), + }; + + var handler = new RpcHandler(this); + rpc.AddLocalRpcMethod("session.event", handler.OnSessionEvent); + rpc.AddLocalRpcMethod("tool.call", handler.OnToolCall); + rpc.AddLocalRpcMethod("permission.request", handler.OnPermissionRequest); rpc.StartListening(); return new Connection(rpc, cliProcess, tcpClient, networkStream); } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Using the Json source generator.")] - [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Using the Json source generator.")] - static IJsonRpcMessageFormatter CreateFormatter() + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Using happy path from https://microsoft.github.io/vs-streamjsonrpc/docs/nativeAOT.html")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Using happy path from https://microsoft.github.io/vs-streamjsonrpc/docs/nativeAOT.html")] + private static SystemTextJsonFormatter CreateSystemTextJsonFormatter() => + new SystemTextJsonFormatter() { JsonSerializerOptions = SerializerOptionsForMessageFormatter }; + + private static JsonSerializerOptions SerializerOptionsForMessageFormatter { get; } = CreateSerializerOptions(); + + private static JsonSerializerOptions CreateSerializerOptions() { var options = new JsonSerializerOptions(JsonSerializerDefaults.Web) { @@ -770,7 +785,14 @@ static IJsonRpcMessageFormatter CreateFormatter() DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; - return new SystemTextJsonFormatter() { JsonSerializerOptions = options }; + options.TypeInfoResolverChain.Add(ClientJsonContext.Default); + options.TypeInfoResolverChain.Add(TypesJsonContext.Default); + options.TypeInfoResolverChain.Add(CopilotSession.SessionJsonContext.Default); + options.TypeInfoResolverChain.Add(SessionEventsJsonContext.Default); + + options.MakeReadOnly(); + + return options; } internal CopilotSession? GetSession(string sessionId) => @@ -803,9 +825,7 @@ public async ValueTask DisposeAsync() private class RpcHandler(CopilotClient client) { - [JsonRpcMethod("session.event")] - public void OnSessionEvent(string sessionId, - JsonElement? @event) + public void OnSessionEvent(string sessionId, JsonElement? @event) { var session = client.GetSession(sessionId); if (session != null && @event != null) @@ -818,7 +838,6 @@ public void OnSessionEvent(string sessionId, } } - [JsonRpcMethod("tool.call")] public async Task OnToolCall(string sessionId, string toolCallId, string toolName, @@ -891,7 +910,7 @@ public async Task OnToolCall(string sessionId, // something we don't control? an error?) TextResultForLlm = result is JsonElement { ValueKind: JsonValueKind.String } je ? je.GetString()! - : JsonSerializer.Serialize(result, tool.JsonSerializerOptions), + : JsonSerializer.Serialize(result, tool.JsonSerializerOptions.GetTypeInfo(typeof(object))), }; return new ToolCallResponse(toolResultObject); } @@ -908,7 +927,6 @@ public async Task OnToolCall(string sessionId, } } - [JsonRpcMethod("permission.request")] public async Task OnPermissionRequest(string sessionId, JsonElement permissionRequest) { var session = client.GetSession(sessionId); @@ -959,7 +977,7 @@ public static string Escape(string arg) } // Request/Response types for RPC - private record CreateSessionRequest( + internal record CreateSessionRequest( string? Model, string? SessionId, List? Tools, @@ -975,7 +993,7 @@ private record CreateSessionRequest( List? SkillDirectories, List? DisabledSkills); - private record ToolDefinition( + internal record ToolDefinition( string Name, string? Description, JsonElement Parameters /* JSON schema */) @@ -984,10 +1002,10 @@ public static ToolDefinition FromAIFunction(AIFunction function) => new ToolDefinition(function.Name, function.Description, function.JsonSchema); } - private record CreateSessionResponse( + internal record CreateSessionResponse( string SessionId); - private record ResumeSessionRequest( + internal record ResumeSessionRequest( string SessionId, List? Tools, ProviderConfig? Provider, @@ -998,24 +1016,93 @@ private record ResumeSessionRequest( List? SkillDirectories, List? DisabledSkills); - private record ResumeSessionResponse( + internal record ResumeSessionResponse( string SessionId); - private record GetLastSessionIdResponse( + internal record GetLastSessionIdResponse( string? SessionId); - private record DeleteSessionResponse( + internal record DeleteSessionRequest( + string SessionId); + + internal record DeleteSessionResponse( bool Success, string? Error); - private record ListSessionsResponse( + internal record ListSessionsResponse( List Sessions); - private record ToolCallResponse( + internal record ToolCallResponse( ToolResultObject? Result); - private record PermissionRequestResponse( + internal record PermissionRequestResponse( PermissionRequestResult Result); + + /// Trace source that forwards all logs to the ILogger. + internal sealed class LoggerTraceSource : TraceSource + { + public LoggerTraceSource(ILogger logger) : base(nameof(LoggerTraceSource), SourceLevels.All) + { + Listeners.Clear(); + Listeners.Add(new LoggerTraceListener(logger)); + } + + private sealed class LoggerTraceListener(ILogger logger) : TraceListener + { + public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? message) => + logger.Log(MapLevel(eventType), "[{Source}] {Message}", source, message); + + public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? format, params object?[]? args) => + logger.Log(MapLevel(eventType), "[{Source}] {Message}", source, args is null || args.Length == 0 ? format : string.Format(format ?? "", args)); + + public override void TraceData(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, object? data) => + logger.Log(MapLevel(eventType), "[{Source}] {Data}", source, data); + + public override void TraceData(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, params object?[]? data) => + logger.Log(MapLevel(eventType), "[{Source}] {Data}", source, data is null ? null : string.Join(", ", data)); + + public override void Write(string? message) => + logger.LogTrace("{Message}", message); + + public override void WriteLine(string? message) => + logger.LogTrace("{Message}", message); + + private static LogLevel MapLevel(TraceEventType eventType) => eventType switch + { + TraceEventType.Critical => LogLevel.Critical, + TraceEventType.Error => LogLevel.Error, + TraceEventType.Warning => LogLevel.Warning, + TraceEventType.Information => LogLevel.Information, + TraceEventType.Verbose => LogLevel.Debug, + _ => LogLevel.Trace + }; + } + } + + [JsonSourceGenerationOptions( + JsonSerializerDefaults.Web, + AllowOutOfOrderMetadataProperties = true, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] + [JsonSerializable(typeof(CreateSessionRequest))] + [JsonSerializable(typeof(CreateSessionResponse))] + [JsonSerializable(typeof(CustomAgentConfig))] + [JsonSerializable(typeof(DeleteSessionRequest))] + [JsonSerializable(typeof(DeleteSessionResponse))] + [JsonSerializable(typeof(GetLastSessionIdResponse))] + [JsonSerializable(typeof(ListSessionsResponse))] + [JsonSerializable(typeof(PermissionRequestResponse))] + [JsonSerializable(typeof(PermissionRequestResult))] + [JsonSerializable(typeof(ProviderConfig))] + [JsonSerializable(typeof(ResumeSessionRequest))] + [JsonSerializable(typeof(ResumeSessionResponse))] + [JsonSerializable(typeof(SessionMetadata))] + [JsonSerializable(typeof(SystemMessageConfig))] + [JsonSerializable(typeof(ToolCallResponse))] + [JsonSerializable(typeof(ToolDefinition))] + [JsonSerializable(typeof(ToolResultAIContent))] + [JsonSerializable(typeof(ToolResultObject))] + internal partial class ClientJsonContext : JsonSerializerContext; } // Must inherit from AIContent as a signal to MEAI to avoid JSON-serializing the diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index d0fb44e0..487ff684 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -6,1125 +6,1098 @@ // // Generated from: @github/copilot/session-events.schema.json // Generated by: scripts/generate-session-types.ts -// Generated at: 2026-01-22T04:11:05.393Z +// Generated at: 2026-01-22T13:45:56.468Z // // To update these types: // 1. Update the schema in copilot-agent-runtime // 2. Run: npm run generate:session-types -// -#nullable enable - -namespace GitHub.Copilot.SDK +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace GitHub.Copilot.SDK; + +/// +/// Base class for all session events with polymorphic JSON serialization. +/// +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "type", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization)] +[JsonDerivedType(typeof(AbortEvent), "abort")] +[JsonDerivedType(typeof(AssistantIntentEvent), "assistant.intent")] +[JsonDerivedType(typeof(AssistantMessageEvent), "assistant.message")] +[JsonDerivedType(typeof(AssistantMessageDeltaEvent), "assistant.message_delta")] +[JsonDerivedType(typeof(AssistantReasoningEvent), "assistant.reasoning")] +[JsonDerivedType(typeof(AssistantReasoningDeltaEvent), "assistant.reasoning_delta")] +[JsonDerivedType(typeof(AssistantTurnEndEvent), "assistant.turn_end")] +[JsonDerivedType(typeof(AssistantTurnStartEvent), "assistant.turn_start")] +[JsonDerivedType(typeof(AssistantUsageEvent), "assistant.usage")] +[JsonDerivedType(typeof(HookEndEvent), "hook.end")] +[JsonDerivedType(typeof(HookStartEvent), "hook.start")] +[JsonDerivedType(typeof(PendingMessagesModifiedEvent), "pending_messages.modified")] +[JsonDerivedType(typeof(SessionCompactionCompleteEvent), "session.compaction_complete")] +[JsonDerivedType(typeof(SessionCompactionStartEvent), "session.compaction_start")] +[JsonDerivedType(typeof(SessionErrorEvent), "session.error")] +[JsonDerivedType(typeof(SessionHandoffEvent), "session.handoff")] +[JsonDerivedType(typeof(SessionIdleEvent), "session.idle")] +[JsonDerivedType(typeof(SessionInfoEvent), "session.info")] +[JsonDerivedType(typeof(SessionModelChangeEvent), "session.model_change")] +[JsonDerivedType(typeof(SessionResumeEvent), "session.resume")] +[JsonDerivedType(typeof(SessionStartEvent), "session.start")] +[JsonDerivedType(typeof(SessionTruncationEvent), "session.truncation")] +[JsonDerivedType(typeof(SessionUsageInfoEvent), "session.usage_info")] +[JsonDerivedType(typeof(SubagentCompletedEvent), "subagent.completed")] +[JsonDerivedType(typeof(SubagentFailedEvent), "subagent.failed")] +[JsonDerivedType(typeof(SubagentSelectedEvent), "subagent.selected")] +[JsonDerivedType(typeof(SubagentStartedEvent), "subagent.started")] +[JsonDerivedType(typeof(SystemMessageEvent), "system.message")] +[JsonDerivedType(typeof(ToolExecutionCompleteEvent), "tool.execution_complete")] +[JsonDerivedType(typeof(ToolExecutionPartialResultEvent), "tool.execution_partial_result")] +[JsonDerivedType(typeof(ToolExecutionStartEvent), "tool.execution_start")] +[JsonDerivedType(typeof(ToolUserRequestedEvent), "tool.user_requested")] +[JsonDerivedType(typeof(UserMessageEvent), "user.message")] +public abstract partial class SessionEvent { - using System; - using System.Collections.Generic; - using System.Text.Json; - using System.Text.Json.Serialization; - - /// - /// Base class for all session events with polymorphic JSON serialization. - /// - [JsonPolymorphic( - TypeDiscriminatorPropertyName = "type", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization)] - [JsonDerivedType(typeof(AbortEvent), "abort")] - [JsonDerivedType(typeof(AssistantIntentEvent), "assistant.intent")] - [JsonDerivedType(typeof(AssistantMessageEvent), "assistant.message")] - [JsonDerivedType(typeof(AssistantMessageDeltaEvent), "assistant.message_delta")] - [JsonDerivedType(typeof(AssistantReasoningEvent), "assistant.reasoning")] - [JsonDerivedType(typeof(AssistantReasoningDeltaEvent), "assistant.reasoning_delta")] - [JsonDerivedType(typeof(AssistantTurnEndEvent), "assistant.turn_end")] - [JsonDerivedType(typeof(AssistantTurnStartEvent), "assistant.turn_start")] - [JsonDerivedType(typeof(AssistantUsageEvent), "assistant.usage")] - [JsonDerivedType(typeof(HookEndEvent), "hook.end")] - [JsonDerivedType(typeof(HookStartEvent), "hook.start")] - [JsonDerivedType(typeof(PendingMessagesModifiedEvent), "pending_messages.modified")] - [JsonDerivedType(typeof(SessionCompactionCompleteEvent), "session.compaction_complete")] - [JsonDerivedType(typeof(SessionCompactionStartEvent), "session.compaction_start")] - [JsonDerivedType(typeof(SessionErrorEvent), "session.error")] - [JsonDerivedType(typeof(SessionHandoffEvent), "session.handoff")] - [JsonDerivedType(typeof(SessionIdleEvent), "session.idle")] - [JsonDerivedType(typeof(SessionInfoEvent), "session.info")] - [JsonDerivedType(typeof(SessionModelChangeEvent), "session.model_change")] - [JsonDerivedType(typeof(SessionResumeEvent), "session.resume")] - [JsonDerivedType(typeof(SessionStartEvent), "session.start")] - [JsonDerivedType(typeof(SessionTruncationEvent), "session.truncation")] - [JsonDerivedType(typeof(SessionUsageInfoEvent), "session.usage_info")] - [JsonDerivedType(typeof(SubagentCompletedEvent), "subagent.completed")] - [JsonDerivedType(typeof(SubagentFailedEvent), "subagent.failed")] - [JsonDerivedType(typeof(SubagentSelectedEvent), "subagent.selected")] - [JsonDerivedType(typeof(SubagentStartedEvent), "subagent.started")] - [JsonDerivedType(typeof(SystemMessageEvent), "system.message")] - [JsonDerivedType(typeof(ToolExecutionCompleteEvent), "tool.execution_complete")] - [JsonDerivedType(typeof(ToolExecutionPartialResultEvent), "tool.execution_partial_result")] - [JsonDerivedType(typeof(ToolExecutionProgressEvent), "tool.execution_progress")] - [JsonDerivedType(typeof(ToolExecutionStartEvent), "tool.execution_start")] - [JsonDerivedType(typeof(ToolUserRequestedEvent), "tool.user_requested")] - [JsonDerivedType(typeof(UserMessageEvent), "user.message")] - public abstract partial class SessionEvent - { - [JsonPropertyName("id")] - public Guid Id { get; set; } + [JsonPropertyName("id")] + public Guid Id { get; set; } - [JsonPropertyName("timestamp")] - public DateTimeOffset Timestamp { get; set; } + [JsonPropertyName("timestamp")] + public DateTimeOffset Timestamp { get; set; } - [JsonPropertyName("parentId")] - public Guid? ParentId { get; set; } + [JsonPropertyName("parentId")] + public Guid? ParentId { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("ephemeral")] - public bool? Ephemeral { get; set; } - - /// - /// The event type discriminator. - /// - [JsonIgnore] - public abstract string Type { get; } - - public static SessionEvent FromJson(string json) => - JsonSerializer.Deserialize(json, SerializerOptions.Default)!; - - public string ToJson() => - JsonSerializer.Serialize(this, GetType(), SerializerOptions.Default); - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("ephemeral")] + public bool? Ephemeral { get; set; } /// - /// Event: session.start + /// The event type discriminator. /// - public partial class SessionStartEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.start"; + [JsonIgnore] + public abstract string Type { get; } - [JsonPropertyName("data")] - public required SessionStartData Data { get; set; } - } + public static SessionEvent FromJson(string json) => + JsonSerializer.Deserialize(json, SessionEventsJsonContext.Default.SessionEvent)!; - /// - /// Event: session.resume - /// - public partial class SessionResumeEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.resume"; + public string ToJson() => + JsonSerializer.Serialize(this, SessionEventsJsonContext.Default.SessionEvent); +} - [JsonPropertyName("data")] - public required SessionResumeData Data { get; set; } - } +/// +/// Event: session.start +/// +public partial class SessionStartEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.start"; - /// - /// Event: session.error - /// - public partial class SessionErrorEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.error"; + [JsonPropertyName("data")] + public required SessionStartData Data { get; set; } +} - [JsonPropertyName("data")] - public required SessionErrorData Data { get; set; } - } +/// +/// Event: session.resume +/// +public partial class SessionResumeEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.resume"; - /// - /// Event: session.idle - /// - public partial class SessionIdleEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.idle"; + [JsonPropertyName("data")] + public required SessionResumeData Data { get; set; } +} - [JsonPropertyName("data")] - public required SessionIdleData Data { get; set; } - } +/// +/// Event: session.error +/// +public partial class SessionErrorEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.error"; - /// - /// Event: session.info - /// - public partial class SessionInfoEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.info"; + [JsonPropertyName("data")] + public required SessionErrorData Data { get; set; } +} - [JsonPropertyName("data")] - public required SessionInfoData Data { get; set; } - } +/// +/// Event: session.idle +/// +public partial class SessionIdleEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.idle"; - /// - /// Event: session.model_change - /// - public partial class SessionModelChangeEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.model_change"; + [JsonPropertyName("data")] + public required SessionIdleData Data { get; set; } +} - [JsonPropertyName("data")] - public required SessionModelChangeData Data { get; set; } - } - - /// - /// Event: session.handoff - /// - public partial class SessionHandoffEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.handoff"; +/// +/// Event: session.info +/// +public partial class SessionInfoEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.info"; - [JsonPropertyName("data")] - public required SessionHandoffData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionInfoData Data { get; set; } +} - /// - /// Event: session.truncation - /// - public partial class SessionTruncationEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.truncation"; +/// +/// Event: session.model_change +/// +public partial class SessionModelChangeEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.model_change"; - [JsonPropertyName("data")] - public required SessionTruncationData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionModelChangeData Data { get; set; } +} - /// - /// Event: session.usage_info - /// - public partial class SessionUsageInfoEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.usage_info"; +/// +/// Event: session.handoff +/// +public partial class SessionHandoffEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.handoff"; - [JsonPropertyName("data")] - public required SessionUsageInfoData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionHandoffData Data { get; set; } +} - /// - /// Event: session.compaction_start - /// - public partial class SessionCompactionStartEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.compaction_start"; +/// +/// Event: session.truncation +/// +public partial class SessionTruncationEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.truncation"; - [JsonPropertyName("data")] - public required SessionCompactionStartData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionTruncationData Data { get; set; } +} - /// - /// Event: session.compaction_complete - /// - public partial class SessionCompactionCompleteEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "session.compaction_complete"; +/// +/// Event: session.usage_info +/// +public partial class SessionUsageInfoEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.usage_info"; - [JsonPropertyName("data")] - public required SessionCompactionCompleteData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionUsageInfoData Data { get; set; } +} - /// - /// Event: user.message - /// - public partial class UserMessageEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "user.message"; +/// +/// Event: session.compaction_start +/// +public partial class SessionCompactionStartEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.compaction_start"; - [JsonPropertyName("data")] - public required UserMessageData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionCompactionStartData Data { get; set; } +} - /// - /// Event: pending_messages.modified - /// - public partial class PendingMessagesModifiedEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "pending_messages.modified"; +/// +/// Event: session.compaction_complete +/// +public partial class SessionCompactionCompleteEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "session.compaction_complete"; - [JsonPropertyName("data")] - public required PendingMessagesModifiedData Data { get; set; } - } + [JsonPropertyName("data")] + public required SessionCompactionCompleteData Data { get; set; } +} - /// - /// Event: assistant.turn_start - /// - public partial class AssistantTurnStartEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.turn_start"; +/// +/// Event: user.message +/// +public partial class UserMessageEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "user.message"; - [JsonPropertyName("data")] - public required AssistantTurnStartData Data { get; set; } - } + [JsonPropertyName("data")] + public required UserMessageData Data { get; set; } +} - /// - /// Event: assistant.intent - /// - public partial class AssistantIntentEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.intent"; +/// +/// Event: pending_messages.modified +/// +public partial class PendingMessagesModifiedEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "pending_messages.modified"; - [JsonPropertyName("data")] - public required AssistantIntentData Data { get; set; } - } + [JsonPropertyName("data")] + public required PendingMessagesModifiedData Data { get; set; } +} - /// - /// Event: assistant.reasoning - /// - public partial class AssistantReasoningEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.reasoning"; +/// +/// Event: assistant.turn_start +/// +public partial class AssistantTurnStartEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.turn_start"; - [JsonPropertyName("data")] - public required AssistantReasoningData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantTurnStartData Data { get; set; } +} - /// - /// Event: assistant.reasoning_delta - /// - public partial class AssistantReasoningDeltaEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.reasoning_delta"; +/// +/// Event: assistant.intent +/// +public partial class AssistantIntentEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.intent"; - [JsonPropertyName("data")] - public required AssistantReasoningDeltaData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantIntentData Data { get; set; } +} - /// - /// Event: assistant.message - /// - public partial class AssistantMessageEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.message"; +/// +/// Event: assistant.reasoning +/// +public partial class AssistantReasoningEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.reasoning"; - [JsonPropertyName("data")] - public required AssistantMessageData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantReasoningData Data { get; set; } +} - /// - /// Event: assistant.message_delta - /// - public partial class AssistantMessageDeltaEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.message_delta"; +/// +/// Event: assistant.reasoning_delta +/// +public partial class AssistantReasoningDeltaEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.reasoning_delta"; - [JsonPropertyName("data")] - public required AssistantMessageDeltaData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantReasoningDeltaData Data { get; set; } +} - /// - /// Event: assistant.turn_end - /// - public partial class AssistantTurnEndEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.turn_end"; +/// +/// Event: assistant.message +/// +public partial class AssistantMessageEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.message"; - [JsonPropertyName("data")] - public required AssistantTurnEndData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantMessageData Data { get; set; } +} - /// - /// Event: assistant.usage - /// - public partial class AssistantUsageEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "assistant.usage"; +/// +/// Event: assistant.message_delta +/// +public partial class AssistantMessageDeltaEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.message_delta"; - [JsonPropertyName("data")] - public required AssistantUsageData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantMessageDeltaData Data { get; set; } +} - /// - /// Event: abort - /// - public partial class AbortEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "abort"; +/// +/// Event: assistant.turn_end +/// +public partial class AssistantTurnEndEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.turn_end"; - [JsonPropertyName("data")] - public required AbortData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantTurnEndData Data { get; set; } +} - /// - /// Event: tool.user_requested - /// - public partial class ToolUserRequestedEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "tool.user_requested"; +/// +/// Event: assistant.usage +/// +public partial class AssistantUsageEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "assistant.usage"; - [JsonPropertyName("data")] - public required ToolUserRequestedData Data { get; set; } - } + [JsonPropertyName("data")] + public required AssistantUsageData Data { get; set; } +} - /// - /// Event: tool.execution_start - /// - public partial class ToolExecutionStartEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "tool.execution_start"; +/// +/// Event: abort +/// +public partial class AbortEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "abort"; - [JsonPropertyName("data")] - public required ToolExecutionStartData Data { get; set; } - } + [JsonPropertyName("data")] + public required AbortData Data { get; set; } +} - /// - /// Event: tool.execution_partial_result - /// - public partial class ToolExecutionPartialResultEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "tool.execution_partial_result"; +/// +/// Event: tool.user_requested +/// +public partial class ToolUserRequestedEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "tool.user_requested"; - [JsonPropertyName("data")] - public required ToolExecutionPartialResultData Data { get; set; } - } + [JsonPropertyName("data")] + public required ToolUserRequestedData Data { get; set; } +} - /// - /// Event: tool.execution_progress - /// - public partial class ToolExecutionProgressEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "tool.execution_progress"; +/// +/// Event: tool.execution_start +/// +public partial class ToolExecutionStartEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "tool.execution_start"; - [JsonPropertyName("data")] - public required ToolExecutionProgressData Data { get; set; } - } + [JsonPropertyName("data")] + public required ToolExecutionStartData Data { get; set; } +} - /// - /// Event: tool.execution_complete - /// - public partial class ToolExecutionCompleteEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "tool.execution_complete"; +/// +/// Event: tool.execution_partial_result +/// +public partial class ToolExecutionPartialResultEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "tool.execution_partial_result"; - [JsonPropertyName("data")] - public required ToolExecutionCompleteData Data { get; set; } - } + [JsonPropertyName("data")] + public required ToolExecutionPartialResultData Data { get; set; } +} - /// - /// Event: subagent.started - /// - public partial class SubagentStartedEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "subagent.started"; +/// +/// Event: tool.execution_complete +/// +public partial class ToolExecutionCompleteEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "tool.execution_complete"; - [JsonPropertyName("data")] - public required SubagentStartedData Data { get; set; } - } + [JsonPropertyName("data")] + public required ToolExecutionCompleteData Data { get; set; } +} - /// - /// Event: subagent.completed - /// - public partial class SubagentCompletedEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "subagent.completed"; +/// +/// Event: subagent.started +/// +public partial class SubagentStartedEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "subagent.started"; - [JsonPropertyName("data")] - public required SubagentCompletedData Data { get; set; } - } + [JsonPropertyName("data")] + public required SubagentStartedData Data { get; set; } +} - /// - /// Event: subagent.failed - /// - public partial class SubagentFailedEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "subagent.failed"; +/// +/// Event: subagent.completed +/// +public partial class SubagentCompletedEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "subagent.completed"; - [JsonPropertyName("data")] - public required SubagentFailedData Data { get; set; } - } + [JsonPropertyName("data")] + public required SubagentCompletedData Data { get; set; } +} - /// - /// Event: subagent.selected - /// - public partial class SubagentSelectedEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "subagent.selected"; +/// +/// Event: subagent.failed +/// +public partial class SubagentFailedEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "subagent.failed"; - [JsonPropertyName("data")] - public required SubagentSelectedData Data { get; set; } - } + [JsonPropertyName("data")] + public required SubagentFailedData Data { get; set; } +} - /// - /// Event: hook.start - /// - public partial class HookStartEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "hook.start"; +/// +/// Event: subagent.selected +/// +public partial class SubagentSelectedEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "subagent.selected"; - [JsonPropertyName("data")] - public required HookStartData Data { get; set; } - } + [JsonPropertyName("data")] + public required SubagentSelectedData Data { get; set; } +} - /// - /// Event: hook.end - /// - public partial class HookEndEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "hook.end"; +/// +/// Event: hook.start +/// +public partial class HookStartEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "hook.start"; - [JsonPropertyName("data")] - public required HookEndData Data { get; set; } - } + [JsonPropertyName("data")] + public required HookStartData Data { get; set; } +} - /// - /// Event: system.message - /// - public partial class SystemMessageEvent : SessionEvent - { - [JsonIgnore] - public override string Type => "system.message"; +/// +/// Event: hook.end +/// +public partial class HookEndEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "hook.end"; - [JsonPropertyName("data")] - public required SystemMessageData Data { get; set; } - } + [JsonPropertyName("data")] + public required HookEndData Data { get; set; } +} - public partial class SessionStartData - { - [JsonPropertyName("sessionId")] - public required string SessionId { get; set; } +/// +/// Event: system.message +/// +public partial class SystemMessageEvent : SessionEvent +{ + [JsonIgnore] + public override string Type => "system.message"; - [JsonPropertyName("version")] - public required double Version { get; set; } + [JsonPropertyName("data")] + public required SystemMessageData Data { get; set; } +} - [JsonPropertyName("producer")] - public required string Producer { get; set; } +public partial class SessionStartData +{ + [JsonPropertyName("sessionId")] + public required string SessionId { get; set; } - [JsonPropertyName("copilotVersion")] - public required string CopilotVersion { get; set; } + [JsonPropertyName("version")] + public required double Version { get; set; } - [JsonPropertyName("startTime")] - public required DateTimeOffset StartTime { get; set; } + [JsonPropertyName("producer")] + public required string Producer { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("selectedModel")] - public string? SelectedModel { get; set; } + [JsonPropertyName("copilotVersion")] + public required string CopilotVersion { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("context")] - public SessionStartDataContext? Context { get; set; } - } + [JsonPropertyName("startTime")] + public required DateTimeOffset StartTime { get; set; } - public partial class SessionResumeData - { - [JsonPropertyName("resumeTime")] - public required DateTimeOffset ResumeTime { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("selectedModel")] + public string? SelectedModel { get; set; } - [JsonPropertyName("eventCount")] - public required double EventCount { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("context")] + public SessionStartDataContext? Context { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("context")] - public SessionResumeDataContext? Context { get; set; } - } +public partial class SessionResumeData +{ + [JsonPropertyName("resumeTime")] + public required DateTimeOffset ResumeTime { get; set; } - public partial class SessionErrorData - { - [JsonPropertyName("errorType")] - public required string ErrorType { get; set; } + [JsonPropertyName("eventCount")] + public required double EventCount { get; set; } - [JsonPropertyName("message")] - public required string Message { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("context")] + public SessionResumeDataContext? Context { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("stack")] - public string? Stack { get; set; } - } +public partial class SessionErrorData +{ + [JsonPropertyName("errorType")] + public required string ErrorType { get; set; } - public partial class SessionIdleData - { - } + [JsonPropertyName("message")] + public required string Message { get; set; } - public partial class SessionInfoData - { - [JsonPropertyName("infoType")] - public required string InfoType { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stack")] + public string? Stack { get; set; } +} - [JsonPropertyName("message")] - public required string Message { get; set; } - } +public partial class SessionIdleData +{ +} - public partial class SessionModelChangeData - { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("previousModel")] - public string? PreviousModel { get; set; } +public partial class SessionInfoData +{ + [JsonPropertyName("infoType")] + public required string InfoType { get; set; } - [JsonPropertyName("newModel")] - public required string NewModel { get; set; } - } + [JsonPropertyName("message")] + public required string Message { get; set; } +} - public partial class SessionHandoffData - { - [JsonPropertyName("handoffTime")] - public required DateTimeOffset HandoffTime { get; set; } +public partial class SessionModelChangeData +{ + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("previousModel")] + public string? PreviousModel { get; set; } - [JsonPropertyName("sourceType")] - public required SessionHandoffDataSourceType SourceType { get; set; } + [JsonPropertyName("newModel")] + public required string NewModel { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("repository")] - public SessionHandoffDataRepository? Repository { get; set; } +public partial class SessionHandoffData +{ + [JsonPropertyName("handoffTime")] + public required DateTimeOffset HandoffTime { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("context")] - public string? Context { get; set; } + [JsonPropertyName("sourceType")] + public required SessionHandoffDataSourceType SourceType { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("summary")] - public string? Summary { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("repository")] + public SessionHandoffDataRepository? Repository { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("remoteSessionId")] - public string? RemoteSessionId { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("context")] + public string? Context { get; set; } - public partial class SessionTruncationData - { - [JsonPropertyName("tokenLimit")] - public required double TokenLimit { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("summary")] + public string? Summary { get; set; } - [JsonPropertyName("preTruncationTokensInMessages")] - public required double PreTruncationTokensInMessages { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("remoteSessionId")] + public string? RemoteSessionId { get; set; } +} - [JsonPropertyName("preTruncationMessagesLength")] - public required double PreTruncationMessagesLength { get; set; } +public partial class SessionTruncationData +{ + [JsonPropertyName("tokenLimit")] + public required double TokenLimit { get; set; } - [JsonPropertyName("postTruncationTokensInMessages")] - public required double PostTruncationTokensInMessages { get; set; } + [JsonPropertyName("preTruncationTokensInMessages")] + public required double PreTruncationTokensInMessages { get; set; } - [JsonPropertyName("postTruncationMessagesLength")] - public required double PostTruncationMessagesLength { get; set; } + [JsonPropertyName("preTruncationMessagesLength")] + public required double PreTruncationMessagesLength { get; set; } - [JsonPropertyName("tokensRemovedDuringTruncation")] - public required double TokensRemovedDuringTruncation { get; set; } + [JsonPropertyName("postTruncationTokensInMessages")] + public required double PostTruncationTokensInMessages { get; set; } - [JsonPropertyName("messagesRemovedDuringTruncation")] - public required double MessagesRemovedDuringTruncation { get; set; } + [JsonPropertyName("postTruncationMessagesLength")] + public required double PostTruncationMessagesLength { get; set; } - [JsonPropertyName("performedBy")] - public required string PerformedBy { get; set; } - } + [JsonPropertyName("tokensRemovedDuringTruncation")] + public required double TokensRemovedDuringTruncation { get; set; } - public partial class SessionUsageInfoData - { - [JsonPropertyName("tokenLimit")] - public required double TokenLimit { get; set; } + [JsonPropertyName("messagesRemovedDuringTruncation")] + public required double MessagesRemovedDuringTruncation { get; set; } - [JsonPropertyName("currentTokens")] - public required double CurrentTokens { get; set; } + [JsonPropertyName("performedBy")] + public required string PerformedBy { get; set; } +} - [JsonPropertyName("messagesLength")] - public required double MessagesLength { get; set; } - } +public partial class SessionUsageInfoData +{ + [JsonPropertyName("tokenLimit")] + public required double TokenLimit { get; set; } - public partial class SessionCompactionStartData - { - } + [JsonPropertyName("currentTokens")] + public required double CurrentTokens { get; set; } - public partial class SessionCompactionCompleteData - { - [JsonPropertyName("success")] - public required bool Success { get; set; } + [JsonPropertyName("messagesLength")] + public required double MessagesLength { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("error")] - public string? Error { get; set; } +public partial class SessionCompactionStartData +{ +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("preCompactionTokens")] - public double? PreCompactionTokens { get; set; } +public partial class SessionCompactionCompleteData +{ + [JsonPropertyName("success")] + public required bool Success { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("postCompactionTokens")] - public double? PostCompactionTokens { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("error")] + public string? Error { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("preCompactionMessagesLength")] - public double? PreCompactionMessagesLength { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("preCompactionTokens")] + public double? PreCompactionTokens { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("messagesRemoved")] - public double? MessagesRemoved { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("postCompactionTokens")] + public double? PostCompactionTokens { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("tokensRemoved")] - public double? TokensRemoved { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("preCompactionMessagesLength")] + public double? PreCompactionMessagesLength { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("summaryContent")] - public string? SummaryContent { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("messagesRemoved")] + public double? MessagesRemoved { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("compactionTokensUsed")] - public SessionCompactionCompleteDataCompactionTokensUsed? CompactionTokensUsed { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("tokensRemoved")] + public double? TokensRemoved { get; set; } - public partial class UserMessageData - { - [JsonPropertyName("content")] - public required string Content { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("summaryContent")] + public string? SummaryContent { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("transformedContent")] - public string? TransformedContent { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("compactionTokensUsed")] + public SessionCompactionCompleteDataCompactionTokensUsed? CompactionTokensUsed { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("attachments")] - public UserMessageDataAttachmentsItem[]? Attachments { get; set; } +public partial class UserMessageData +{ + [JsonPropertyName("content")] + public required string Content { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("source")] - public string? Source { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("transformedContent")] + public string? TransformedContent { get; set; } - public partial class PendingMessagesModifiedData - { - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("attachments")] + public UserMessageDataAttachmentsItem[]? Attachments { get; set; } - public partial class AssistantTurnStartData - { - [JsonPropertyName("turnId")] - public required string TurnId { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("source")] + public string? Source { get; set; } +} - public partial class AssistantIntentData - { - [JsonPropertyName("intent")] - public required string Intent { get; set; } - } +public partial class PendingMessagesModifiedData +{ +} - public partial class AssistantReasoningData - { - [JsonPropertyName("reasoningId")] - public required string ReasoningId { get; set; } +public partial class AssistantTurnStartData +{ + [JsonPropertyName("turnId")] + public required string TurnId { get; set; } +} - [JsonPropertyName("content")] - public required string Content { get; set; } - } +public partial class AssistantIntentData +{ + [JsonPropertyName("intent")] + public required string Intent { get; set; } +} - public partial class AssistantReasoningDeltaData - { - [JsonPropertyName("reasoningId")] - public required string ReasoningId { get; set; } +public partial class AssistantReasoningData +{ + [JsonPropertyName("reasoningId")] + public required string ReasoningId { get; set; } - [JsonPropertyName("deltaContent")] - public required string DeltaContent { get; set; } - } + [JsonPropertyName("content")] + public required string Content { get; set; } +} - public partial class AssistantMessageData - { - [JsonPropertyName("messageId")] - public required string MessageId { get; set; } +public partial class AssistantReasoningDeltaData +{ + [JsonPropertyName("reasoningId")] + public required string ReasoningId { get; set; } - [JsonPropertyName("content")] - public required string Content { get; set; } + [JsonPropertyName("deltaContent")] + public required string DeltaContent { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("toolRequests")] - public AssistantMessageDataToolRequestsItem[]? ToolRequests { get; set; } +public partial class AssistantMessageData +{ + [JsonPropertyName("messageId")] + public required string MessageId { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("parentToolCallId")] - public string? ParentToolCallId { get; set; } - } + [JsonPropertyName("content")] + public required string Content { get; set; } - public partial class AssistantMessageDeltaData - { - [JsonPropertyName("messageId")] - public required string MessageId { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("toolRequests")] + public AssistantMessageDataToolRequestsItem[]? ToolRequests { get; set; } - [JsonPropertyName("deltaContent")] - public required string DeltaContent { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("parentToolCallId")] + public string? ParentToolCallId { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("totalResponseSizeBytes")] - public double? TotalResponseSizeBytes { get; set; } +public partial class AssistantMessageDeltaData +{ + [JsonPropertyName("messageId")] + public required string MessageId { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("parentToolCallId")] - public string? ParentToolCallId { get; set; } - } + [JsonPropertyName("deltaContent")] + public required string DeltaContent { get; set; } - public partial class AssistantTurnEndData - { - [JsonPropertyName("turnId")] - public required string TurnId { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("totalResponseSizeBytes")] + public double? TotalResponseSizeBytes { get; set; } - public partial class AssistantUsageData - { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("model")] - public string? Model { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("parentToolCallId")] + public string? ParentToolCallId { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("inputTokens")] - public double? InputTokens { get; set; } +public partial class AssistantTurnEndData +{ + [JsonPropertyName("turnId")] + public required string TurnId { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("outputTokens")] - public double? OutputTokens { get; set; } +public partial class AssistantUsageData +{ + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("model")] + public string? Model { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("cacheReadTokens")] - public double? CacheReadTokens { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("inputTokens")] + public double? InputTokens { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("cacheWriteTokens")] - public double? CacheWriteTokens { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("outputTokens")] + public double? OutputTokens { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("cost")] - public double? Cost { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cacheReadTokens")] + public double? CacheReadTokens { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("duration")] - public double? Duration { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cacheWriteTokens")] + public double? CacheWriteTokens { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("initiator")] - public string? Initiator { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cost")] + public double? Cost { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("apiCallId")] - public string? ApiCallId { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("duration")] + public double? Duration { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("providerCallId")] - public string? ProviderCallId { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("initiator")] + public string? Initiator { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("quotaSnapshots")] - public Dictionary? QuotaSnapshots { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("apiCallId")] + public string? ApiCallId { get; set; } - public partial class AbortData - { - [JsonPropertyName("reason")] - public required string Reason { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("providerCallId")] + public string? ProviderCallId { get; set; } - public partial class ToolUserRequestedData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("quotaSnapshots")] + public Dictionary? QuotaSnapshots { get; set; } +} - [JsonPropertyName("toolName")] - public required string ToolName { get; set; } +public partial class AbortData +{ + [JsonPropertyName("reason")] + public required string Reason { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("arguments")] - public object? Arguments { get; set; } - } +public partial class ToolUserRequestedData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - public partial class ToolExecutionStartData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } + [JsonPropertyName("toolName")] + public required string ToolName { get; set; } - [JsonPropertyName("toolName")] - public required string ToolName { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("arguments")] + public object? Arguments { get; set; } +} - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("arguments")] - public object? Arguments { get; set; } +public partial class ToolExecutionStartData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("parentToolCallId")] - public string? ParentToolCallId { get; set; } - } + [JsonPropertyName("toolName")] + public required string ToolName { get; set; } - public partial class ToolExecutionPartialResultData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("arguments")] + public object? Arguments { get; set; } - [JsonPropertyName("partialOutput")] - public required string PartialOutput { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("parentToolCallId")] + public string? ParentToolCallId { get; set; } +} - public partial class ToolExecutionProgressData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } +public partial class ToolExecutionPartialResultData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonPropertyName("progressMessage")] - public required string ProgressMessage { get; set; } - } + [JsonPropertyName("partialOutput")] + public required string PartialOutput { get; set; } +} - public partial class ToolExecutionCompleteData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } +public partial class ToolExecutionCompleteData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonPropertyName("success")] - public required bool Success { get; set; } + [JsonPropertyName("success")] + public required bool Success { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("isUserRequested")] - public bool? IsUserRequested { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("isUserRequested")] + public bool? IsUserRequested { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("result")] - public ToolExecutionCompleteDataResult? Result { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("result")] + public ToolExecutionCompleteDataResult? Result { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("error")] - public ToolExecutionCompleteDataError? Error { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("error")] + public ToolExecutionCompleteDataError? Error { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("toolTelemetry")] - public Dictionary? ToolTelemetry { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("toolTelemetry")] + public Dictionary? ToolTelemetry { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("parentToolCallId")] - public string? ParentToolCallId { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("parentToolCallId")] + public string? ParentToolCallId { get; set; } +} - public partial class SubagentStartedData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } +public partial class SubagentStartedData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonPropertyName("agentName")] - public required string AgentName { get; set; } + [JsonPropertyName("agentName")] + public required string AgentName { get; set; } - [JsonPropertyName("agentDisplayName")] - public required string AgentDisplayName { get; set; } + [JsonPropertyName("agentDisplayName")] + public required string AgentDisplayName { get; set; } - [JsonPropertyName("agentDescription")] - public required string AgentDescription { get; set; } - } + [JsonPropertyName("agentDescription")] + public required string AgentDescription { get; set; } +} - public partial class SubagentCompletedData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } +public partial class SubagentCompletedData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonPropertyName("agentName")] - public required string AgentName { get; set; } - } + [JsonPropertyName("agentName")] + public required string AgentName { get; set; } +} - public partial class SubagentFailedData - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } +public partial class SubagentFailedData +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonPropertyName("agentName")] - public required string AgentName { get; set; } + [JsonPropertyName("agentName")] + public required string AgentName { get; set; } - [JsonPropertyName("error")] - public required string Error { get; set; } - } + [JsonPropertyName("error")] + public required string Error { get; set; } +} - public partial class SubagentSelectedData - { - [JsonPropertyName("agentName")] - public required string AgentName { get; set; } +public partial class SubagentSelectedData +{ + [JsonPropertyName("agentName")] + public required string AgentName { get; set; } - [JsonPropertyName("agentDisplayName")] - public required string AgentDisplayName { get; set; } + [JsonPropertyName("agentDisplayName")] + public required string AgentDisplayName { get; set; } - [JsonPropertyName("tools")] - public string[]? Tools { get; set; } - } + [JsonPropertyName("tools")] + public string[]? Tools { get; set; } +} - public partial class HookStartData - { - [JsonPropertyName("hookInvocationId")] - public required string HookInvocationId { get; set; } +public partial class HookStartData +{ + [JsonPropertyName("hookInvocationId")] + public required string HookInvocationId { get; set; } - [JsonPropertyName("hookType")] - public required string HookType { get; set; } + [JsonPropertyName("hookType")] + public required string HookType { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("input")] - public object? Input { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("input")] + public object? Input { get; set; } +} - public partial class HookEndData - { - [JsonPropertyName("hookInvocationId")] - public required string HookInvocationId { get; set; } +public partial class HookEndData +{ + [JsonPropertyName("hookInvocationId")] + public required string HookInvocationId { get; set; } - [JsonPropertyName("hookType")] - public required string HookType { get; set; } + [JsonPropertyName("hookType")] + public required string HookType { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("output")] - public object? Output { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("output")] + public object? Output { get; set; } - [JsonPropertyName("success")] - public required bool Success { get; set; } + [JsonPropertyName("success")] + public required bool Success { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("error")] - public HookEndDataError? Error { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("error")] + public HookEndDataError? Error { get; set; } +} - public partial class SystemMessageData - { - [JsonPropertyName("content")] - public required string Content { get; set; } +public partial class SystemMessageData +{ + [JsonPropertyName("content")] + public required string Content { get; set; } - [JsonPropertyName("role")] - public required SystemMessageDataRole Role { get; set; } + [JsonPropertyName("role")] + public required SystemMessageDataRole Role { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("name")] - public string? Name { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("name")] + public string? Name { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("metadata")] - public SystemMessageDataMetadata? Metadata { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("metadata")] + public SystemMessageDataMetadata? Metadata { get; set; } +} - public partial class SessionStartDataContext - { - [JsonPropertyName("cwd")] - public required string Cwd { get; set; } +public partial class SessionStartDataContext +{ + [JsonPropertyName("cwd")] + public required string Cwd { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("gitRoot")] - public string? GitRoot { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("gitRoot")] + public string? GitRoot { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("repository")] - public string? Repository { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("repository")] + public string? Repository { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("branch")] - public string? Branch { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("branch")] + public string? Branch { get; set; } +} - public partial class SessionResumeDataContext - { - [JsonPropertyName("cwd")] - public required string Cwd { get; set; } +public partial class SessionResumeDataContext +{ + [JsonPropertyName("cwd")] + public required string Cwd { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("gitRoot")] - public string? GitRoot { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("gitRoot")] + public string? GitRoot { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("repository")] - public string? Repository { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("repository")] + public string? Repository { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("branch")] - public string? Branch { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("branch")] + public string? Branch { get; set; } +} - public partial class SessionHandoffDataRepository - { - [JsonPropertyName("owner")] - public required string Owner { get; set; } +public partial class SessionHandoffDataRepository +{ + [JsonPropertyName("owner")] + public required string Owner { get; set; } - [JsonPropertyName("name")] - public required string Name { get; set; } + [JsonPropertyName("name")] + public required string Name { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("branch")] - public string? Branch { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("branch")] + public string? Branch { get; set; } +} - public partial class SessionCompactionCompleteDataCompactionTokensUsed - { - [JsonPropertyName("input")] - public required double Input { get; set; } +public partial class SessionCompactionCompleteDataCompactionTokensUsed +{ + [JsonPropertyName("input")] + public required double Input { get; set; } - [JsonPropertyName("output")] - public required double Output { get; set; } + [JsonPropertyName("output")] + public required double Output { get; set; } - [JsonPropertyName("cachedInput")] - public required double CachedInput { get; set; } - } + [JsonPropertyName("cachedInput")] + public required double CachedInput { get; set; } +} - public partial class UserMessageDataAttachmentsItem - { - [JsonPropertyName("type")] - public required UserMessageDataAttachmentsItemType Type { get; set; } +public partial class UserMessageDataAttachmentsItem +{ + [JsonPropertyName("type")] + public required UserMessageDataAttachmentsItemType Type { get; set; } - [JsonPropertyName("path")] - public required string Path { get; set; } + [JsonPropertyName("path")] + public required string Path { get; set; } - [JsonPropertyName("displayName")] - public required string DisplayName { get; set; } - } + [JsonPropertyName("displayName")] + public required string DisplayName { get; set; } +} - public partial class AssistantMessageDataToolRequestsItem - { - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } +public partial class AssistantMessageDataToolRequestsItem +{ + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } - [JsonPropertyName("name")] - public required string Name { get; set; } + [JsonPropertyName("name")] + public required string Name { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("arguments")] - public object? Arguments { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("arguments")] + public object? Arguments { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("type")] - public AssistantMessageDataToolRequestsItemType? Type { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("type")] + public AssistantMessageDataToolRequestsItemType? Type { get; set; } +} - public partial class ToolExecutionCompleteDataResult - { - [JsonPropertyName("content")] - public required string Content { get; set; } - } +public partial class ToolExecutionCompleteDataResult +{ + [JsonPropertyName("content")] + public required string Content { get; set; } +} - public partial class ToolExecutionCompleteDataError - { - [JsonPropertyName("message")] - public required string Message { get; set; } +public partial class ToolExecutionCompleteDataError +{ + [JsonPropertyName("message")] + public required string Message { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("code")] - public string? Code { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("code")] + public string? Code { get; set; } +} - public partial class HookEndDataError - { - [JsonPropertyName("message")] - public required string Message { get; set; } +public partial class HookEndDataError +{ + [JsonPropertyName("message")] + public required string Message { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("stack")] - public string? Stack { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stack")] + public string? Stack { get; set; } +} - public partial class SystemMessageDataMetadata - { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("promptVersion")] - public string? PromptVersion { get; set; } +public partial class SystemMessageDataMetadata +{ + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("promptVersion")] + public string? PromptVersion { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("variables")] - public Dictionary? Variables { get; set; } - } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("variables")] + public Dictionary? Variables { get; set; } +} [JsonConverter(typeof(JsonStringEnumConverter))] public enum SessionHandoffDataSourceType @@ -1162,16 +1135,86 @@ public enum SystemMessageDataRole Developer, } - internal static class SerializerOptions - { - /// - /// Default options for polymorphic deserialization. - /// - public static readonly JsonSerializerOptions Default = new() - { - AllowOutOfOrderMetadataProperties = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - } -} \ No newline at end of file +[JsonSourceGenerationOptions( + JsonSerializerDefaults.Web, + AllowOutOfOrderMetadataProperties = true, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] +[JsonSerializable(typeof(AbortData))] +[JsonSerializable(typeof(AbortEvent))] +[JsonSerializable(typeof(AssistantIntentData))] +[JsonSerializable(typeof(AssistantIntentEvent))] +[JsonSerializable(typeof(AssistantMessageData))] +[JsonSerializable(typeof(AssistantMessageDataToolRequestsItem))] +[JsonSerializable(typeof(AssistantMessageDeltaData))] +[JsonSerializable(typeof(AssistantMessageDeltaEvent))] +[JsonSerializable(typeof(AssistantMessageEvent))] +[JsonSerializable(typeof(AssistantReasoningData))] +[JsonSerializable(typeof(AssistantReasoningDeltaData))] +[JsonSerializable(typeof(AssistantReasoningDeltaEvent))] +[JsonSerializable(typeof(AssistantReasoningEvent))] +[JsonSerializable(typeof(AssistantTurnEndData))] +[JsonSerializable(typeof(AssistantTurnEndEvent))] +[JsonSerializable(typeof(AssistantTurnStartData))] +[JsonSerializable(typeof(AssistantTurnStartEvent))] +[JsonSerializable(typeof(AssistantUsageData))] +[JsonSerializable(typeof(AssistantUsageEvent))] +[JsonSerializable(typeof(HookEndData))] +[JsonSerializable(typeof(HookEndDataError))] +[JsonSerializable(typeof(HookEndEvent))] +[JsonSerializable(typeof(HookStartData))] +[JsonSerializable(typeof(HookStartEvent))] +[JsonSerializable(typeof(PendingMessagesModifiedData))] +[JsonSerializable(typeof(PendingMessagesModifiedEvent))] +[JsonSerializable(typeof(SessionCompactionCompleteData))] +[JsonSerializable(typeof(SessionCompactionCompleteDataCompactionTokensUsed))] +[JsonSerializable(typeof(SessionCompactionCompleteEvent))] +[JsonSerializable(typeof(SessionCompactionStartData))] +[JsonSerializable(typeof(SessionCompactionStartEvent))] +[JsonSerializable(typeof(SessionErrorData))] +[JsonSerializable(typeof(SessionErrorEvent))] +[JsonSerializable(typeof(SessionEvent))] +[JsonSerializable(typeof(SessionHandoffData))] +[JsonSerializable(typeof(SessionHandoffDataRepository))] +[JsonSerializable(typeof(SessionHandoffEvent))] +[JsonSerializable(typeof(SessionIdleData))] +[JsonSerializable(typeof(SessionIdleEvent))] +[JsonSerializable(typeof(SessionInfoData))] +[JsonSerializable(typeof(SessionInfoEvent))] +[JsonSerializable(typeof(SessionModelChangeData))] +[JsonSerializable(typeof(SessionModelChangeEvent))] +[JsonSerializable(typeof(SessionResumeData))] +[JsonSerializable(typeof(SessionResumeDataContext))] +[JsonSerializable(typeof(SessionResumeEvent))] +[JsonSerializable(typeof(SessionStartData))] +[JsonSerializable(typeof(SessionStartDataContext))] +[JsonSerializable(typeof(SessionStartEvent))] +[JsonSerializable(typeof(SessionTruncationData))] +[JsonSerializable(typeof(SessionTruncationEvent))] +[JsonSerializable(typeof(SessionUsageInfoData))] +[JsonSerializable(typeof(SessionUsageInfoEvent))] +[JsonSerializable(typeof(SubagentCompletedData))] +[JsonSerializable(typeof(SubagentCompletedEvent))] +[JsonSerializable(typeof(SubagentFailedData))] +[JsonSerializable(typeof(SubagentFailedEvent))] +[JsonSerializable(typeof(SubagentSelectedData))] +[JsonSerializable(typeof(SubagentSelectedEvent))] +[JsonSerializable(typeof(SubagentStartedData))] +[JsonSerializable(typeof(SubagentStartedEvent))] +[JsonSerializable(typeof(SystemMessageData))] +[JsonSerializable(typeof(SystemMessageDataMetadata))] +[JsonSerializable(typeof(SystemMessageEvent))] +[JsonSerializable(typeof(ToolExecutionCompleteData))] +[JsonSerializable(typeof(ToolExecutionCompleteDataError))] +[JsonSerializable(typeof(ToolExecutionCompleteDataResult))] +[JsonSerializable(typeof(ToolExecutionCompleteEvent))] +[JsonSerializable(typeof(ToolExecutionPartialResultData))] +[JsonSerializable(typeof(ToolExecutionPartialResultEvent))] +[JsonSerializable(typeof(ToolExecutionStartData))] +[JsonSerializable(typeof(ToolExecutionStartEvent))] +[JsonSerializable(typeof(ToolUserRequestedData))] +[JsonSerializable(typeof(ToolUserRequestedEvent))] +[JsonSerializable(typeof(UserMessageData))] +[JsonSerializable(typeof(UserMessageDataAttachmentsItem))] +[JsonSerializable(typeof(UserMessageEvent))] +internal partial class SessionEventsJsonContext : JsonSerializerContext; \ No newline at end of file diff --git a/dotnet/src/GitHub.Copilot.SDK.csproj b/dotnet/src/GitHub.Copilot.SDK.csproj index 7e9404f7..10cfd98a 100644 --- a/dotnet/src/GitHub.Copilot.SDK.csproj +++ b/dotnet/src/GitHub.Copilot.SDK.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -14,6 +14,7 @@ README.md https://github.com/github/copilot-sdk github;copilot;sdk;jsonrpc;agent + true @@ -23,7 +24,7 @@ - + diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 011cb99b..e554e034 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -6,6 +6,7 @@ using StreamJsonRpc; using System.Text.Json; using System.Text.Json.Nodes; +using System.Text.Json.Serialization; namespace GitHub.Copilot.SDK; @@ -40,7 +41,7 @@ namespace GitHub.Copilot.SDK; /// await session.SendAndWaitAsync(new MessageOptions { Prompt = "Hello, world!" }); /// /// -public class CopilotSession : IAsyncDisposable +public partial class CopilotSession : IAsyncDisposable { private readonly HashSet _eventHandlers = new(); private readonly Dictionary _toolHandlers = new(); @@ -304,7 +305,7 @@ internal async Task HandlePermissionRequestAsync(JsonEl }; } - var request = JsonSerializer.Deserialize(permissionRequestData.GetRawText()) + var request = JsonSerializer.Deserialize(permissionRequestData.GetRawText(), SessionJsonContext.Default.PermissionRequest) ?? throw new InvalidOperationException("Failed to deserialize permission request"); var invocation = new PermissionInvocation @@ -340,7 +341,7 @@ internal async Task HandlePermissionRequestAsync(JsonEl public async Task> GetMessagesAsync(CancellationToken cancellationToken = default) { var response = await _rpc.InvokeWithCancellationAsync( - "session.getMessages", [new { sessionId = SessionId }], cancellationToken); + "session.getMessages", [new GetMessagesRequest { SessionId = SessionId }], cancellationToken); return response.Events .Select(e => SessionEvent.FromJson(e.ToJsonString())) @@ -374,7 +375,7 @@ public async Task> GetMessagesAsync(CancellationToke public async Task AbortAsync(CancellationToken cancellationToken = default) { await _rpc.InvokeWithCancellationAsync( - "session.abort", [new { sessionId = SessionId }], cancellationToken); + "session.abort", [new SessionAbortRequest { SessionId = SessionId }], cancellationToken); } /// @@ -405,7 +406,7 @@ await _rpc.InvokeWithCancellationAsync( public async ValueTask DisposeAsync() { await _rpc.InvokeWithCancellationAsync( - "session.destroy", [new { sessionId = SessionId }]); + "session.destroy", [new SessionDestroyRequest() { SessionId = SessionId }]); _eventHandlers.Clear(); _toolHandlers.Clear(); @@ -426,7 +427,7 @@ private class OnDisposeCall(Action callback) : IDisposable public void Dispose() => callback(); } - private record SendMessageRequest + internal record SendMessageRequest { public string SessionId { get; init; } = string.Empty; public string Prompt { get; init; } = string.Empty; @@ -434,13 +435,43 @@ private record SendMessageRequest public string? Mode { get; init; } } - private record SendMessageResponse + internal record SendMessageResponse { public string MessageId { get; init; } = string.Empty; } - private record GetMessagesResponse + internal record GetMessagesRequest + { + public string SessionId { get; init; } = string.Empty; + } + + internal record GetMessagesResponse { public List Events { get; init; } = new(); } + + internal record SessionAbortRequest + { + public string SessionId { get; init; } = string.Empty; + } + + internal record SessionDestroyRequest + { + public string SessionId { get; init; } = string.Empty; + } + + [JsonSourceGenerationOptions( + JsonSerializerDefaults.Web, + AllowOutOfOrderMetadataProperties = true, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] + [JsonSerializable(typeof(GetMessagesRequest))] + [JsonSerializable(typeof(GetMessagesResponse))] + [JsonSerializable(typeof(PermissionRequest))] + [JsonSerializable(typeof(SendMessageRequest))] + [JsonSerializable(typeof(SendMessageResponse))] + [JsonSerializable(typeof(SessionAbortRequest))] + [JsonSerializable(typeof(SessionDestroyRequest))] + [JsonSerializable(typeof(UserMessageDataAttachmentsItem))] + internal partial class SessionJsonContext : JsonSerializerContext; } diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 68a24217..6abbb42b 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -2,6 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ +using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.Extensions.AI; using Microsoft.Extensions.Logging; @@ -407,6 +408,11 @@ public class SessionMetadata public bool IsRemote { get; set; } } +internal class PingRequest +{ + public string? Message { get; set; } +} + public class PingResponse { public string Message { get; set; } = string.Empty; @@ -560,3 +566,37 @@ public class GetModelsResponse [JsonPropertyName("models")] public List Models { get; set; } = new(); } + +[JsonSourceGenerationOptions( + JsonSerializerDefaults.Web, + AllowOutOfOrderMetadataProperties = true, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] +[JsonSerializable(typeof(AzureOptions))] +[JsonSerializable(typeof(CustomAgentConfig))] +[JsonSerializable(typeof(GetAuthStatusResponse))] +[JsonSerializable(typeof(GetModelsResponse))] +[JsonSerializable(typeof(GetStatusResponse))] +[JsonSerializable(typeof(McpLocalServerConfig))] +[JsonSerializable(typeof(McpRemoteServerConfig))] +[JsonSerializable(typeof(MessageOptions))] +[JsonSerializable(typeof(ModelBilling))] +[JsonSerializable(typeof(ModelCapabilities))] +[JsonSerializable(typeof(ModelInfo))] +[JsonSerializable(typeof(ModelLimits))] +[JsonSerializable(typeof(ModelPolicy))] +[JsonSerializable(typeof(ModelSupports))] +[JsonSerializable(typeof(ModelVisionLimits))] +[JsonSerializable(typeof(PermissionRequest))] +[JsonSerializable(typeof(PermissionRequestResult))] +[JsonSerializable(typeof(PingRequest))] +[JsonSerializable(typeof(PingResponse))] +[JsonSerializable(typeof(ProviderConfig))] +[JsonSerializable(typeof(SessionMetadata))] +[JsonSerializable(typeof(SystemMessageConfig))] +[JsonSerializable(typeof(ToolBinaryResult))] +[JsonSerializable(typeof(ToolInvocation))] +[JsonSerializable(typeof(ToolResultObject))] +[JsonSerializable(typeof(JsonElement))] +[JsonSerializable(typeof(JsonElement?))] +internal partial class TypesJsonContext : JsonSerializerContext; diff --git a/dotnet/test/GitHub.Copilot.SDK.Test.csproj b/dotnet/test/GitHub.Copilot.SDK.Test.csproj index 7a21dd9b..9ead8805 100644 --- a/dotnet/test/GitHub.Copilot.SDK.Test.csproj +++ b/dotnet/test/GitHub.Copilot.SDK.Test.csproj @@ -8,6 +8,16 @@ false + + + false + + @@ -19,7 +29,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/dotnet/test/Harness/CapiProxy.cs b/dotnet/test/Harness/CapiProxy.cs index dd7ba31c..18e21a46 100644 --- a/dotnet/test/Harness/CapiProxy.cs +++ b/dotnet/test/Harness/CapiProxy.cs @@ -6,12 +6,13 @@ using System.Net.Http.Json; using System.Runtime.InteropServices; using System.Text; +using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; namespace GitHub.Copilot.SDK.Test.Harness; -public class CapiProxy : IAsyncDisposable +public partial class CapiProxy : IAsyncDisposable { private Process? _process; private Task? _startupTask; @@ -113,16 +114,18 @@ public async Task ConfigureAsync(string filePath, string workDir) var url = await (_startupTask ?? throw new InvalidOperationException("Proxy not started")); using var client = new HttpClient(); - var response = await client.PostAsJsonAsync($"{url}/config", new { filePath, workDir }); + var response = await client.PostAsJsonAsync($"{url}/config", new ConfigureRequest(filePath, workDir), CapiProxyJsonContext.Default.ConfigureRequest); response.EnsureSuccessStatusCode(); } + private record ConfigureRequest(string FilePath, string WorkDir); + public async Task> GetExchangesAsync() { var url = await (_startupTask ?? throw new InvalidOperationException("Proxy not started")); using var client = new HttpClient(); - return await client.GetFromJsonAsync>($"{url}/exchanges") + return await client.GetFromJsonAsync($"{url}/exchanges", CapiProxyJsonContext.Default.ListParsedHttpExchange) ?? new List(); } @@ -139,6 +142,11 @@ private static string FindRepoRoot() } throw new InvalidOperationException("Could not find repository root"); } + + [JsonSourceGenerationOptions(JsonSerializerDefaults.Web)] + [JsonSerializable(typeof(ConfigureRequest))] + [JsonSerializable(typeof(List))] + private partial class CapiProxyJsonContext : JsonSerializerContext; } public record ParsedHttpExchange(ChatCompletionRequest Request, ChatCompletionResponse? Response); diff --git a/dotnet/test/ToolsTests.cs b/dotnet/test/ToolsTests.cs index 7a4fcee9..3d7741c9 100644 --- a/dotnet/test/ToolsTests.cs +++ b/dotnet/test/ToolsTests.cs @@ -5,12 +5,14 @@ using GitHub.Copilot.SDK.Test.Harness; using Microsoft.Extensions.AI; using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; using Xunit; using Xunit.Abstractions; namespace GitHub.Copilot.SDK.Test; -public class ToolsTests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "tools", output) +public partial class ToolsTests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "tools", output) { [Fact] public async Task Invokes_Built_In_Tools() @@ -102,7 +104,7 @@ public async Task Can_Receive_And_Return_Complex_Types() ToolInvocation? receivedInvocation = null; var session = await Client.CreateSessionAsync(new SessionConfig { - Tools = [AIFunctionFactory.Create(PerformDbQuery, "db_query")], + Tools = [AIFunctionFactory.Create(PerformDbQuery, "db_query", serializerOptions: ToolsTestsJsonContext.Default.Options)], }); await session.SendAsync(new MessageOptions @@ -137,6 +139,12 @@ City[] PerformDbQuery(DbQueryOptions query, AIFunctionArguments rawArgs) record DbQueryOptions(string Table, int[] Ids, bool SortAscending); record City(int CountryId, string CityName, int Population); + [JsonSourceGenerationOptions(JsonSerializerDefaults.Web)] + [JsonSerializable(typeof(DbQueryOptions))] + [JsonSerializable(typeof(City[]))] + [JsonSerializable(typeof(JsonElement))] + private partial class ToolsTestsJsonContext : JsonSerializerContext; + [Fact(Skip = "Behaves as if no content was in the result. Likely that binary results aren't fully implemented yet.")] public async Task Can_Return_Binary_Result() { diff --git a/nodejs/scripts/generate-csharp-session-types.ts b/nodejs/scripts/generate-csharp-session-types.ts index 24a0bf6e..dc2e82b9 100644 --- a/nodejs/scripts/generate-csharp-session-types.ts +++ b/nodejs/scripts/generate-csharp-session-types.ts @@ -235,7 +235,6 @@ function extractEventVariants(schema: JSONSchema7): EventVariant[] { */ function generateDataClass( variant: EventVariant, - indent: string, knownTypes: Map, nestedClasses: Map, enumOutput: string[] @@ -244,14 +243,14 @@ function generateDataClass( const dataSchema = variant.dataSchema; if (!dataSchema?.properties) { - lines.push(`${indent}public partial class ${variant.dataClassName} { }`); + lines.push(`public partial class ${variant.dataClassName} { }`); return lines.join("\n"); } const required = new Set(dataSchema.required || []); - lines.push(`${indent}public partial class ${variant.dataClassName}`); - lines.push(`${indent}{`); + lines.push(`public partial class ${variant.dataClassName}`); + lines.push(`{`); for (const [propName, propSchema] of Object.entries(dataSchema.properties)) { if (typeof propSchema !== "object") continue; @@ -263,7 +262,6 @@ function generateDataClass( variant.dataClassName, csharpName, isRequired, - indent, knownTypes, nestedClasses, enumOutput @@ -272,13 +270,13 @@ function generateDataClass( const isNullableType = csharpType.endsWith("?"); if (!isRequired) { lines.push( - `${indent} [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` + ` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` ); } - lines.push(`${indent} [JsonPropertyName("${propName}")]`); + lines.push(` [JsonPropertyName("${propName}")]`); const requiredModifier = isRequired && !isNullableType ? "required " : ""; - lines.push(`${indent} public ${requiredModifier}${csharpType} ${csharpName} { get; set; }`); + lines.push(` public ${requiredModifier}${csharpType} ${csharpName} { get; set; }`); lines.push(""); } @@ -287,7 +285,7 @@ function generateDataClass( lines.pop(); } - lines.push(`${indent}}`); + lines.push(`}`); return lines.join("\n"); } @@ -298,7 +296,6 @@ function generateDataClass( function generateNestedClass( className: string, schema: JSONSchema7, - indent: string, knownTypes: Map, nestedClasses: Map, enumOutput: string[] @@ -306,8 +303,8 @@ function generateNestedClass( const lines: string[] = []; const required = new Set(schema.required || []); - lines.push(`${indent}public partial class ${className}`); - lines.push(`${indent}{`); + lines.push(`public partial class ${className}`); + lines.push(`{`); if (schema.properties) { for (const [propName, propSchema] of Object.entries(schema.properties)) { @@ -320,7 +317,6 @@ function generateNestedClass( className, csharpName, isRequired, - indent, knownTypes, nestedClasses, enumOutput @@ -328,14 +324,14 @@ function generateNestedClass( if (!isRequired) { lines.push( - `${indent} [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` + ` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` ); } - lines.push(`${indent} [JsonPropertyName("${propName}")]`); + lines.push(` [JsonPropertyName("${propName}")]`); const isNullableType = csharpType.endsWith("?"); const requiredModifier = isRequired && !isNullableType ? "required " : ""; - lines.push(`${indent} public ${requiredModifier}${csharpType} ${csharpName} { get; set; }`); + lines.push(` public ${requiredModifier}${csharpType} ${csharpName} { get; set; }`); lines.push(""); } } @@ -345,7 +341,7 @@ function generateNestedClass( lines.pop(); } - lines.push(`${indent}}`); + lines.push(`}`); return lines.join("\n"); } @@ -358,7 +354,6 @@ function resolvePropertyType( parentClassName: string, propName: string, isRequired: boolean, - indent: string, knownTypes: Map, nestedClasses: Map, enumOutput: string[] @@ -378,7 +373,6 @@ function resolvePropertyType( parentClassName, propName, isRequired && !hasNull, - indent, knownTypes, nestedClasses, enumOutput @@ -405,7 +399,6 @@ function resolvePropertyType( const nestedCode = generateNestedClass( nestedClassName, propSchema, - indent, knownTypes, nestedClasses, enumOutput @@ -424,7 +417,6 @@ function resolvePropertyType( const nestedCode = generateNestedClass( itemClassName, items, - indent, knownTypes, nestedClasses, enumOutput @@ -478,7 +470,6 @@ export function generateCSharpSessionTypes(schema: JSONSchema7, generatedAt: str const knownTypes = new Map(); const nestedClasses = new Map(); const enumOutput: string[] = []; - const indent = " "; const lines: string[] = []; @@ -497,88 +488,83 @@ export function generateCSharpSessionTypes(schema: JSONSchema7, generatedAt: str // 1. Update the schema in copilot-agent-runtime // 2. Run: npm run generate:session-types -// -#nullable enable +using System.Text.Json; +using System.Text.Json.Serialization; -namespace GitHub.Copilot.SDK -{ - using System; - using System.Collections.Generic; - using System.Text.Json; - using System.Text.Json.Serialization; +namespace GitHub.Copilot.SDK; `); // Generate base class with JsonPolymorphic attributes - lines.push(`${indent}/// `); + lines.push(`/// `); lines.push( - `${indent}/// Base class for all session events with polymorphic JSON serialization.` + `/// Base class for all session events with polymorphic JSON serialization.` ); - lines.push(`${indent}/// `); - lines.push(`${indent}[JsonPolymorphic(`); - lines.push(`${indent} TypeDiscriminatorPropertyName = "type", `); + lines.push(`/// `); + lines.push(`[JsonPolymorphic(`); + lines.push(` TypeDiscriminatorPropertyName = "type", `); lines.push( - `${indent} UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization)]` + ` UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization)]` ); // Generate JsonDerivedType attributes for each variant (alphabetized) for (const variant of [...variants].sort((a, b) => a.typeName.localeCompare(b.typeName))) { lines.push( - `${indent}[JsonDerivedType(typeof(${variant.className}), "${variant.typeName}")]` + `[JsonDerivedType(typeof(${variant.className}), "${variant.typeName}")]` ); } - lines.push(`${indent}public abstract partial class SessionEvent`); - lines.push(`${indent}{`); - lines.push(`${indent} [JsonPropertyName("id")]`); - lines.push(`${indent} public Guid Id { get; set; }`); + lines.push(`public abstract partial class SessionEvent`); + lines.push(`{`); + lines.push(` [JsonPropertyName("id")]`); + lines.push(` public Guid Id { get; set; }`); lines.push(""); - lines.push(`${indent} [JsonPropertyName("timestamp")]`); - lines.push(`${indent} public DateTimeOffset Timestamp { get; set; }`); + lines.push(` [JsonPropertyName("timestamp")]`); + lines.push(` public DateTimeOffset Timestamp { get; set; }`); lines.push(""); - lines.push(`${indent} [JsonPropertyName("parentId")]`); - lines.push(`${indent} public Guid? ParentId { get; set; }`); + lines.push(` [JsonPropertyName("parentId")]`); + lines.push(` public Guid? ParentId { get; set; }`); lines.push(""); - lines.push(`${indent} [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); - lines.push(`${indent} [JsonPropertyName("ephemeral")]`); - lines.push(`${indent} public bool? Ephemeral { get; set; }`); + lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); + lines.push(` [JsonPropertyName("ephemeral")]`); + lines.push(` public bool? Ephemeral { get; set; }`); lines.push(""); - lines.push(`${indent} /// `); - lines.push(`${indent} /// The event type discriminator.`); - lines.push(`${indent} /// `); - lines.push(`${indent} [JsonIgnore]`); - lines.push(`${indent} public abstract string Type { get; }`); + lines.push(` /// `); + lines.push(` /// The event type discriminator.`); + lines.push(` /// `); + lines.push(` [JsonIgnore]`); + lines.push(` public abstract string Type { get; }`); lines.push(""); - lines.push(`${indent} public static SessionEvent FromJson(string json) =>`); + lines.push(` public static SessionEvent FromJson(string json) =>`); lines.push( - `${indent} JsonSerializer.Deserialize(json, SerializerOptions.Default)!;` + ` JsonSerializer.Deserialize(json, SessionEventsJsonContext.Default.SessionEvent)!;` ); lines.push(""); - lines.push(`${indent} public string ToJson() =>`); + lines.push(` public string ToJson() =>`); lines.push( - `${indent} JsonSerializer.Serialize(this, GetType(), SerializerOptions.Default);` + ` JsonSerializer.Serialize(this, SessionEventsJsonContext.Default.SessionEvent);` ); - lines.push(`${indent}}`); + lines.push(`}`); lines.push(""); // Generate each event class for (const variant of variants) { - lines.push(`${indent}/// `); - lines.push(`${indent}/// Event: ${variant.typeName}`); - lines.push(`${indent}/// `); - lines.push(`${indent}public partial class ${variant.className} : SessionEvent`); - lines.push(`${indent}{`); - lines.push(`${indent} [JsonIgnore]`); - lines.push(`${indent} public override string Type => "${variant.typeName}";`); + lines.push(`/// `); + lines.push(`/// Event: ${variant.typeName}`); + lines.push(`/// `); + lines.push(`public partial class ${variant.className} : SessionEvent`); + lines.push(`{`); + lines.push(` [JsonIgnore]`); + lines.push(` public override string Type => "${variant.typeName}";`); lines.push(""); - lines.push(`${indent} [JsonPropertyName("data")]`); - lines.push(`${indent} public required ${variant.dataClassName} Data { get; set; }`); - lines.push(`${indent}}`); + lines.push(` [JsonPropertyName("data")]`); + lines.push(` public required ${variant.dataClassName} Data { get; set; }`); + lines.push(`}`); lines.push(""); } // Generate data classes for (const variant of variants) { - const dataClass = generateDataClass(variant, indent, knownTypes, nestedClasses, enumOutput); + const dataClass = generateDataClass(variant, knownTypes, nestedClasses, enumOutput); lines.push(dataClass); lines.push(""); } @@ -594,22 +580,36 @@ namespace GitHub.Copilot.SDK lines.push(enumCode); } - // Generate serializer options - lines.push(`${indent}internal static class SerializerOptions`); - lines.push(`${indent}{`); - lines.push(`${indent} /// `); - lines.push(`${indent} /// Default options for polymorphic deserialization.`); - lines.push(`${indent} /// `); - lines.push(`${indent} public static readonly JsonSerializerOptions Default = new()`); - lines.push(`${indent} {`); - lines.push(`${indent} AllowOutOfOrderMetadataProperties = true,`); - lines.push(`${indent} PropertyNamingPolicy = JsonNamingPolicy.CamelCase,`); - lines.push(`${indent} DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull`); - lines.push(`${indent} };`); - lines.push(`${indent}}`); - - // Close namespace - lines.push(`}`); + // Collect all serializable types (sorted alphabetically) + const serializableTypes: string[] = []; + + // Add SessionEvent base class + serializableTypes.push("SessionEvent"); + + // Add all event classes and their data classes + for (const variant of variants) { + serializableTypes.push(variant.className); + serializableTypes.push(variant.dataClassName); + } + + // Add all nested classes + for (const [className] of nestedClasses) { + serializableTypes.push(className); + } + + // Sort alphabetically + serializableTypes.sort((a, b) => a.localeCompare(b)); + + // Generate JsonSerializerContext with JsonSerializable attributes + lines.push(`[JsonSourceGenerationOptions(`); + lines.push(` JsonSerializerDefaults.Web,`); + lines.push(` AllowOutOfOrderMetadataProperties = true,`); + lines.push(` NumberHandling = JsonNumberHandling.AllowReadingFromString,`); + lines.push(` DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]`); + for (const typeName of serializableTypes) { + lines.push(`[JsonSerializable(typeof(${typeName}))]`); + } + lines.push(`internal partial class SessionEventsJsonContext : JsonSerializerContext;`); return lines.join("\n"); }