Skip to content

fix(codegen): extend discriminated union detection to support 'type' field#3

Merged
birdmanmandbir merged 3 commits intomainfrom
worker/fix-extend-codegen-generate
Mar 4, 2026
Merged

fix(codegen): extend discriminated union detection to support 'type' field#3
birdmanmandbir merged 3 commits intomainfrom
worker/fix-extend-codegen-generate

Conversation

@birdmanmandbir
Copy link
Contributor

Summary

  • Extended isDiscriminatedUnion() to detect both method and type field discriminators (was only method)
  • Added discriminatorField() helper that returns the discriminator field name
  • New genTypeDiscriminatedUnion() generates: struct with Type string + json.RawMessage Data, custom UnmarshalJSON/MarshalJSON, type constants, and typed As*() getter methods
  • Covers ThreadItem (14 variants), ResponseItem (11), UserInput (5), EventMsg (75), and 20+ other oneOf types using type as discriminator

Test plan

  • go build ./... passes
  • go test ./... passes
  • No duplicate type definitions across generated files
  • Generated unions have correct struct, marshal/unmarshal, constants, and getter methods

…field

Previously isDiscriminatedUnion() only checked for 'method' field
discriminators (JSON-RPC style). Now also detects 'type' field
discriminators used by ThreadItem (14 variants), ResponseItem (11),
UserInput (5), EventMsg (75), and 20+ other oneOf types.

Generated pattern for type-unions: struct with Type string +
json.RawMessage Data, custom UnmarshalJSON/MarshalJSON, type constants,
and typed As*() getter methods for each variant.
@birdmanmandbir
Copy link
Contributor Author

PR Review: fix(codegen): extend discriminated union detection

Summary

This PR extends the code generator to handle type-discriminated unions (discriminated by a type field with enum values) in addition to the existing method-discriminated unions (discriminated by a method field). This affects types like EventMsg, ThreadItem, ResponseItem, UserInput, AgentMessageContent, and many others.

Changes

  • cmd/codegen/main.go: Refactored isDiscriminatedUnion() into discriminatorField() returning the field name (method/type/""). Added genTypeDiscriminatedUnion() that generates a wrapper struct with Type string + Data json.RawMessage, custom JSON marshal/unmarshal, type constants, and As*() getter methods for each variant.
  • protocol/types_gen.go: Variant structs moved from here into unions_gen.go (generated inline by the union generator). Net removal of ~1400 lines.
  • protocol/unions_gen.go: Now contains the full union types with struct definitions, JSON handling, constants, and accessor methods. Net addition of ~4200 lines.

Verification

  • go build ./... — passes
  • go vet ./... — passes
  • go test ./... — passes
  • Schema analysis confirms all type-discriminated unions have the type enum on every variant — no partial coverage issues.
  • No union has both method and type discriminators, so the priority check in discriminatorField() is safe.

Findings

No critical issues found.

Minor observations (non-blocking):

  1. Untyped string constants for type discriminators — The type-discriminator constants (EventMsgTypeError = "error") are untyped strings, while method-discriminator constants use a typed string (MethodXxx ClientRequestMethod = "method/xxx"). This is fine functionally but means type-discriminator constants don't get compile-time type safety when used with switch statements. Consistent either way is fine for a generated SDK.

  2. MarshalJSON fallback — When Data is nil, MarshalJSON serializes only {"type": "..."}. This is reasonable for zero-value structs but means constructing a typed union programmatically requires populating Data manually. Fine for a read-heavy SDK.

  3. u.Data = append(u.Data[:0], data...) — Correctly avoids sharing the backing array with the caller's slice. Good.

VERDICT: LGTM

golangci-lint-action@v6 pulled golangci-lint v1.x built with Go 1.24,
which fails against go.mod targeting Go 1.25.5. Action v9 uses
golangci-lint v2.x which supports newer Go versions.
@birdmanmandbir
Copy link
Contributor Author

Triage Update

Review verdict: LGTM — no critical issues.

CI fix: golangci-lint-action upgraded v6→v9 (v6 pulled lint v1.x built with Go 1.24, incompatible with our Go 1.25.5). Also fixed staticcheck S1039 (unnecessary fmt.Sprintf).

CI status: All checks passing.

Merging.

@birdmanmandbir birdmanmandbir merged commit 7e62ec4 into main Mar 4, 2026
1 check passed
@birdmanmandbir birdmanmandbir deleted the worker/fix-extend-codegen-generate branch March 4, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant