feat!: regenerate SDK for API 2026-09-13 with consent-challenge voice cloning - #16
Conversation
|
Holding this as draft until the SSE response is modelled upstream. Live verification against production found
Also found:
All of this is in generated code, so the fixes belong in the Fern definition. The release-please wiring in this PR is verified and stays as-is. Everything else passed: 20/23 live cases, all 10 endpoints exercised, both new subpath exports resolve in ESM and CJS, |
Covers .fern/metadata.json, stamps the Fern-generated version strings from the release tag at publish time, corrects repository.url casing for npm provenance, restores AGENTS.md + manual-publish.yml, and gates publish on a version/tag assertion. src/BaseClient.ts is Fern-generated and cannot be .fernignore'd, so an x-release-please-version marker does not survive there: every regeneration strips it and the generic updater goes back to silently no-opping, leaving X-Fern-SDK-Version and User-Agent reporting a version the SDK is not. That is why main ships 3.0.1 while sending 2.0.1. src/version.ts was shielded in .fernignore as a workaround for the same problem, but 3e8ea41 had already proven regen wins. Both generic extra-files entries and both markers are gone, and src/version.ts leaves .fernignore so Fern owns it again. The publish job now rewrites those literals from the release tag, and the stamp fails when a target literal is not found, so a regeneration that renames or restructures those lines breaks the release loudly instead of shipping a stale version silently. Order is stamp, build, assert, publish: the build emits dist/, which is what npm ships, so a stamp after it would fix the sources and still publish stale strings inside the artifact. The assertion covers dist/ in both CJS and ESM as well as the sources, so a build that missed the stamp cannot pass. The stamp applies to the CI checkout only and is never committed back, so those strings read stale on main between releases by design; the published artifact is always built from the stamped and asserted tree. AGENTS.md documents this so it does not get "fixed" later.
dc26fdb to
42f1b8a
Compare
streamWithTimestamps constructed core.Stream with no eventDiscriminator, routing SSE through iterDataMessages(). That parser drops the event: name, cannot concatenate a multi-line data: field, and discards a trailing event with no terminating blank line. The discarded trailing event is speech.done, which carries billable_characters_count. Passing eventDiscriminator: "type" routes to iterSseEvents() and fixes all three. The live API sends a populated event: speech.chunk name and also duplicates type in the payload. The generated wire fixture showing an empty event: does not match the API. core.Stream assigned a private AbortController that nothing read, and registered an abort listener closing over this. The handler was therefore a no-op, and a reused AbortSignal retained every Stream. Both are replaced with throwIfAborted(). The abort unit test passed on its own break statement rather than on the abort. It is rewritten so it fails when abort breaks. README and reference streaming examples now narrow on item.type, handle speech.error (yielded, never thrown, because the 200 is already committed) and show the base64 decode. .fernignore shields these until the Fern TypeScript generator emits the discriminator. fern-python-sdk@5.14.20 already generates a correct discriminated union on type from the same API definition; fern-typescript-sdk@3.70.1 emits none.
The fern-api[bot] regeneration in commit 6898297 reverted the version-bearing properties from 4.0.0 back to 3.0.2. This restores 4.0.0 in package.json, src/version.ts, .fern/metadata.json sdkVersion, and the X-Fern-SDK-Version and User-Agent literals in src/BaseClient.ts. This PR is a major release: it carries a "Release-As: 4.0.0" footer plus three "BREAKING CHANGE:" footers in its body, which is what reaches main on squash merge and drives the next version. .release-please-manifest.json is deliberately left at 3.0.1. Setting it to 4.0.0 would make release-please treat 4.0.0 as already released and never cut the tag. No files were added to .fernignore. package.json and .fern/metadata.json must stay regenerable, and a future regen clobbering these strings again is a known two-writer conflict between Fern and release-please, not something to fix by shielding.
This reverts commit d267778. The fern-api[bot] rollback to 3.0.2 in 6898297 was correct by design. AGENTS.md is explicit that SDK_VERSION in src/version.ts and the X-Fern-SDK-Version and User-Agent literals in src/BaseClient.ts are stamped from the release tag in the CI checkout at publish time and never committed back, so they are expected to read stale on the branch. Pinning them by hand buys nothing and is called out as something not to do. package.json version and .fern/metadata.json sdkVersion are owned by release-please and set as part of the release PR. Both are addressed structurally, by a known field and a jsonpath, so a regen cannot disarm them. The Release-As: 4.0.0 footer in the PR body is what drives the next version.
POST /v1/audio/speech and streamWithTimestamps return 413 payload_too_large for oversized bodies, but the audio client surfaced it as a generic SpeechifyError. Wire the typed ContentTooLargeError on the audio client to match the voices client. Client.ts is .fernignore-shielded so this survives regeneration.
🤖 I have created a release *beep* *boop* --- ## [4.0.0](3.0.1...4.0.0) (2026-08-19) ### ⚠ BREAKING CHANGES * default API version is now `2026-09-13`. ### Features * regenerate SDK for API 2026-09-13 with consent-challenge voice cloning ([#16](#16)) ([23a8e2f](23a8e2f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
SDK regeneration against API version
2026-09-13. Adds the models endpoint, the consent-challenge flow for voice cloning, and streaming with word-level timestamps. Also repairs the release-please wiring so a release bumps every version-bearing file.Breaking changes
voices.create()signatureThe
consent: stringparameter is gone. Voice cloning now goes through a two-step consent challenge, and the create carries a second audio file — the speaker reading the challenge phrase aloud.A challenge is single-use and expires — see
challenge.expires_at, which is the only authority on the window.audio.stream()request shapeaudio.stream()now takesStreamAudioRequestinstead ofGetStreamRequest.Acceptstays a top-level header field; every body field moves under a new requiredbodyproperty.GetStreamRequesthas not been removed — it is now the body type (StreamAudioRequest["body"]) and has moved fromresources/audio/client/requests/toapi/types/.Default API version
Bumped from
2026-07-07to2026-09-13. Passversionexplicitly to stay on the old behaviour.New
client.models.list()— available TTS modelsclient.voices.consentChallenges.create()— consent challenge flowclient.audio.streamWithTimestamps()— SSE stream with word-level speech marksvoices.list()filters:type,locale,gender,modelContentTooLargeError(413) and new error codesStreamclass for JSON/SSE streamingRelease wiring
The generic release-please updater was silently no-opping —
maincurrently ships3.0.1while reportingX-Fern-SDK-Version: 2.0.1. Fixed here:x-release-please-versionmarkers.src/BaseClient.tsis Fern-generated and cannot be.fernignored — Fern legitimately owns it — so every regen strips the marker and thegenericupdater silently goes back to no-opping. Bothgenericextra-filesentries and both marker comments are gone.src/version.tsleaves.fernignoretoo: it no longer needs shielding, so Fern owns it again.SDK_VERSION,X-Fern-SDK-Version, theUser-Agentversion, andpackage.jsonversionfromtag_name. The stamp fails when a target literal is missing, so a regen that renames or restructures those lines breaks the release loudly instead of shipping a stale version silently. Prerelease suffixes survive verbatim (4.0.0-alpha.1).pnpm buildemitsdist/, anddist/is what npm ships — a stamp placed after it would fix the sources and still publish the stale strings baked into the artifact. Order is stamp → build → assert → publish, and the assertion now coversdist/in both CJS and ESM as well as the sources..fern/metadata.jsontoextra-files(it was stale at2.0.1). It is jsonpath-based, so no marker is involved and a regen cannot disarm it.repository.urlcasing toSpeechify-AI; npm provenance 422s on a case-inexact URL.AGENTS.mdandmanual-publish.yml, both now in.fernignore.dist/— or the repository URL disagrees with the tag.The stamp rewrites the CI checkout only and is never committed back, so
src/version.tsandsrc/BaseClient.tsread stale onmainbetween releases by design; the published artifact is always built from the stamped and asserted tree.AGENTS.mddocuments this so it does not get "fixed" later.Verified by executing the stamp and assertion scripts extracted from the workflow YAML against sandbox copies of the repo: matching tag, un-stamped tree at
4.0.0, assert-without-stamp control, three renamed/restructured literals, empty tag, non-semver tag, prerelease4.0.0-alpha.1, lowercaserepository.url, adist/built before the stamp, a missingdist/, and a repeat run for idempotency — 51 assertions, all passing. Running release-please's own updaters against the new config for4.0.0confirmspackage.jsonand.fern/metadata.jsonstill update and that zero entries depend on a marker.pnpm buildandpnpm testare clean (29 files, 523 tests).Merge with squash so the conventional title and this footer land on
main.BREAKING CHANGE:
voices.create()no longer acceptsconsent; it requiresconsent_challenge_idandconsent_recording.BREAKING CHANGE:
audio.stream()takesStreamAudioRequestwith body fields nested underbody.BREAKING CHANGE: default API version is now
2026-09-13.Release-As: 4.0.0