fix(all): report server-sent event operations and field deprecations in SDK diffs
MF
2d ago+487+487+012345678901234567890123456789-25-25-01234567890123456789
[skip changelog]
Why
speakeasy diff and the release notes that speakeasy run writes to gen.lock both build SDK ASTs through pkg/changes. Two gaps made those diffs incomplete.
- Operations with a
text/event-streamresponse disappeared from the diff.resolveASTran the generator with a context that carried no generation access state. When the generator reaches an event-stream response, it callslicensing.ValidateAccountHasFeatureAccess. Without access state, that check returnsErrMissingGenerationAccess, which is wrapped as anUnsupportedError, andg.skipsilently drops the whole operation. Because the operation was missing from both the old and new AST, it was never reported as added or removed, and changes to its request or response (for example a new enum value) were never reported either. This hits both an operation whose 200 response offersapplication/jsonandtext/event-stream, and an operation that only streams. The same gate covers other feature-gated constructs, such as JSONL responses and webhooks. - Field deprecation was ignored.
diffFieldDefscompares nullability, optionality, defaults, consts and annotations, but notComments.Deprecated. So marking a request or response fielddeprecated: trueproduced no change.
What changed
resolveASTattaches direct generation access state when the caller supplies none. This matchesinternal/generate.Generate. Callers that already provide access state are unaffected.- A field that becomes deprecated is now reported with a new
field_deprecateddiff reason, rendered as**Deprecated**. It is non-breaking, and only the transition into deprecation is reported, consistent with method-level deprecation. If the field also changed in another way, it is still reported as**Changed**. - The duplicated reason-to-action switches in
markdown.goare now oneformatDiffActionhelper.
Before (old spec has generateReport with a json + event-stream 200 response; new spec adds the html enum value to its request, adds createWidget (json + event-stream) and tailEvents (event-stream only)):
No changes detected.
After:
## Python SDK Changes:
* `sdk.create_widget()`: **Added**
* `sdk.tail_events()`: **Added**
* `sdk.generate_report()`:
* `request.format.enum(html)` **Added**
Before (request field color and response field nickname marked deprecated: true):
No changes detected.
After:
## Typescript SDK Changes:
* `sdk.updateWidget()`:
* `request.color` **Deprecated**
* `response.nickname` **Deprecated**
No generated SDK output changes, so this PR skips the changelog.
Testing
- New snapshot tests
TestChanges_MethodChanges_ServerSentEventsandTestChanges_FieldChanges_FieldDeprecated. Both fail withCI=trueagainst the previouspkg/changessources and pass with this change. go test ./pkg/changes/... ./cmd/changes/...passes, with no changes to existing snapshots.golangci-lint run ./pkg/changes/...reports 0 issues.make lintalso reports a gofmt issue intemplates/perms.go, which is unchanged frommain.- Ran
go run ./cmd/changeson a pair of specs combining json + event-stream operations, an enum addition and a deprecated response field. All expected changes are now reported. git diff --checkflags only trailing spaces in the new snapshots. Those are literal markdown output (:before a nested list), the same as in 43 existing snapshots.
Public-safety check
- This change contains no credentials, customer documents, private repository URLs, private filesystem paths, or unredacted private logs.
- Title, body, comments, and commit messages name no customers or customer-derived identifiers, private paths or trackers, or workflow provenance, and are understandable without private context (
.claude/skills/public-repo-communication/SKILL.md). - Generated fixtures and review SDK changes are public-safe.
- I reviewed
git diff --check.
Summary by cubic
Fixes two gaps that made speakeasy diff and release notes written to gen.lock miss real SDK changes.
- Operations with
text/event-streamresponses were dropped becauseresolveASTran the generator without generation access state; it now attaches direct access state when none is provided, matchinginternal/generate.Generate. This also covers other feature-gated constructs such as JSONL responses and webhooks. - Marking a request or response field
deprecated: trueproduced no change; fields that become deprecated are now reported with a newfield_deprecateddiff reason, rendered as**Deprecated**. Only the transition into deprecation is reported, consistent with method-level deprecation, and fields that also changed otherwise are still reported as**Changed**. - The duplicated reason-to-action switches in
markdown.goare now oneformatDiffActionhelper.
No generated SDK output changes, so the changelog is skipped.