Skip to content

Tighten the generated SDK runtime and finish the gosdk rename - #631

Merged
daveshanley merged 1 commit into
mainfrom
claude/sdk-followups
Sep 22, 2026
Merged

daveshanley merged 1 commit into
mainfrom
claude/sdk-followups

Conversation

@daveshanley

Copy link
Copy Markdown
Member

Follow-up to #626. I merged that one before the last of the review residuals landed, so here they are on their own branch.

The one that was on me

In the 626 review I said "seed a bytes.Buffer from Content-Length". The implementation did exactly that, and it made small bodies worse. bytes.Buffer.ReadFrom reserves bytes.MinRead (512) before every read, including the final one that reports EOF, so Grow(Content-Length) still reallocates. A 12-byte JSON body cost 1.6KB and 4 to 5 allocs where plain io.ReadAll cost 584B and 3.

readBody now reserves the headroom when the length is declared and falls back to io.ReadAll when it is unknown, over the limit, or not addressable. A 1MB body is 1.06MB and 3 allocs, against 2.2MB and 26 on the original path.

Credentials applied in place

authorize cloned the entire request for every complete alternative. The clone only matters when a failed Apply could leave partial writes behind and a later alternative could still run. That is now the only case that clones. Everything else applies straight to the request.

One Widgets.List call, stub doer ns/op B/op allocs/op
main today 2067 5560 45
this branch 1696 3656 38

Finishing the rename

package gosdk was living in a directory called golang, under a doc comment that said "Package golang", with 48 error strings prefixed sdk/golang:. The directory is now generator/sdk/gosdk and the name is carried through the doc comment, the README, the generated file headers and the error prefix (gosdk:).

This moves an import path. No tag contains the 626 merge yet (latest is v0.38.7), so it is free today and a breaking change after the next release. Worth landing before one is cut.

Two smaller things

  • Reachability and collection were two copies of the same schema walk. They now share forEachShapeChild, so they cannot disagree about what gets generated. Neither callback heap-allocates.
  • generator/golang has one scalar mapping. ScalarType takes the JSON type and format, and goType uses the same builtinScalarType, so SDK parameter types and model field types come from one place. ScalarType changed signature, which is fine for the same reason the rename is: it has never been released.

Tests

The generated -race suite gained two cases. One proves a credential that fails part-way through an alternative does not leak into the fallback request (it fails with the clone removed, showing Authorization: Bearer token riding along with the service key). The other proves Content-Length is a preallocation hint and never a bound: declared, absent, understated and over-limit all behave.

All three generator packages stay at 100%, and every block this branch touches is covered.

Deliberately left alone

  • newRequest still parses the path, stringifies the endpoint, and lets http.NewRequestWithContext parse it again. That is about 3 of the remaining 38 allocs. The clean fix changes how URLs are assembled for malformed path templates, so it wants its own PR with table tests on URL assembly.
  • A time.Time parameter encoder. With Options.Models wired, mapping date-time to time.Time makes any date-time parameter a generation error until one exists. Next increment.
  • The workflow inputs schema helper belongs on higharazzo.Workflow as public API, because the engine will want it. That is a call about the core model's surface, so it is not riding in here.
  • The test that swaps the package-level templates to force render failures stays. There is no codecov config in the repo, so the default auto targets apply and removing it would drop project coverage.

🤖 Generated with Claude Code

Follow-up to #626, which merged before these review residuals landed.

Generated runtime:
- Read response bodies through readBody. bytes.Buffer.ReadFrom reserves
  bytes.MinRead before every read, so Grow(Content-Length) alone still
  reallocated and a 12-byte body cost 1.6KB. Reserve the headroom when
  the length is declared and fall back to io.ReadAll when it is not.
- Apply credentials in place. authorize cloned the whole request for
  every complete alternative; it now clones only when a later
  alternative could still run, which is the one case where a failed
  Apply can leak partial writes.

One Widgets.List call against a stub doer goes from 2067ns, 5560B and
45 allocs to 1696ns, 3656B and 38 allocs.

Emitter:
- Rename generator/sdk/golang to generator/sdk/gosdk so the directory
  matches the package, and carry the name through the doc comment, the
  README, the generated file headers and the error prefix. No tag
  contains the merge yet, so the import path is still free to move.
- Share one shape walk (forEachShapeChild) between reachability and
  collection so the two cannot disagree about what is generated.
- Give generator/golang a single scalar mapping. ScalarType now takes
  the JSON type and format, and goType uses the same builtinScalarType,
  so SDK parameters and model fields cannot drift.

Tests: the generated -race suite now proves a failed alternative does
not leak into its fallback (it fails with the clone removed) and that
Content-Length is a preallocation hint, never a bound.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.87%. Comparing base (54dc125) to head (5dfb86c).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #631      +/-   ##
==========================================
+ Coverage   99.79%   99.87%   +0.08%     
==========================================
  Files         288      296       +8     
  Lines       35523    37147    +1624     
==========================================
+ Hits        35449    37101    +1652     
+ Misses         46       27      -19     
+ Partials       28       19       -9     
Flag Coverage Δ
unittests 99.87% <100.00%> (+0.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@daveshanley
daveshanley merged commit 64654b7 into main Sep 22, 2026
8 checks passed
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