-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Go session events codegen: flat union type causes breaking changes when adding new event types #1031
Description
Problem
The Go codegen for session events (generated_session_events.go) uses quicktype, which represents the discriminated union of all session event Data payloads as a single flat struct with every property from every event type merged together:
type Data struct {
Content *string // from assistant.message
Title *string // from session.title_changed
ToolName *string // from tool.execution_start
// ... hundreds of fields from all event types
}This means that if a new session event type is added that has a property with the same name but a different type as an existing event, the shared field must change type to accommodate both. For example, content was *string but a new event used content as a structured object — quicktype changed it to *DataContent (a union of string and map), breaking all existing consumers that read Content as *string.
This is fundamentally unmanageable: any new session event type can silently break the Go SDK's public API by changing the type of a field that existing consumers rely on.
Impact
- Every
go/generated_session_events.goregeneration is a potential breaking change - SDK consumers cannot safely use
response.Data.Content(or any shared field) without risking that a future codegen run changes its type - We had to revert the session events codegen in PR Add modelCapabilities override to all SDK languages #1029 because it introduced a breaking
Contenttype change unrelated to the PR's purpose
Desired outcome
A representation of session event data that is additive-only — adding a new event type should never change the types of existing event payloads. Some options:
-
Per-event-type structs: Generate a separate struct for each event type's data (e.g.,
AssistantMessageData,ToolExecutionStartData), with a typed accessor onSessionEventthat returns the concrete type based on theTypediscriminator. This is what the C# codegen does. -
Embed + type-switch: Keep a minimal base struct with common fields, and generate per-event structs that consumers access via a type switch or typed getter method.
-
Interface-based: Define a
SessionEventDatainterface with per-type implementations, using a customUnmarshalJSONthat dispatches based on thetypefield.
All of these ensure that adding event type B never changes the struct shape of event type A.
Current workaround
In #1029 I explicitly reverted the Go-specific session events codegen change, and added a build check suppression (09f7cee). When we fix the code generator, we must also re-enable the build check.