Skip to content

feat(regen): add diarize_info, Flux force-end-turn, update-listen, word speaker confidence - #89

Merged
GregHolmes merged 15 commits into
mainfrom
gh/sdk-gen-2026-07-31
Jul 31, 2026
Merged

feat(regen): add diarize_info, Flux force-end-turn, update-listen, word speaker confidence#89
GregHolmes merged 15 commits into
mainfrom
gh/sdk-gen-2026-07-31

Conversation

@GregHolmes

@GregHolmes GregHolmes commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

SDK regeneration for 2026-07-31 against fern-java-sdk 4.16.0, generated from the deepgram-docs sdk-gen-2026-07-31 branch (coordinate fix deepgram/deepgram-docs#1069 + Flux non-breaking reshape deepgram/deepgram-docs#1064 + cherry-picked spec PRs deepgram/deepgram-docs#1066, deepgram/deepgram-docs#1063, deepgram/deepgram-docs#1036, deepgram/deepgram-docs#1047).

Source-compatible with 0.7.x — no breaking changes

Verified by a full breaking-change sweep against 0.7.1 (public API diffed from compiled trees): zero deleted public types, zero renames, zero removed or retyped getters — 1414 public types and 10,999 public members all still present. The generator (4.16.0) introduced several source-breaking changes that are shimmed back below.

Two caveats on "purely additive", for the record:

  • The new provider() overloads on AgentV1UpdateListenListen make a bare provider(null) ambiguous, so that one call no longer compiles. No working 0.7.x program is affected — it already threw NullPointerException from Objects.requireNonNull.
  • ProviderStage gained two abstract methods, which technically breaks anyone implementing that generated builder-stage interface directly.

New functionality (additive)

  • diarize_info in listen v1 response metadata (deepgram-docs#1036)
  • ListenV2ForceEndTurn + sendForceEndTurn(...) on the listen v2 WS client (deepgram-docs#1047)
  • UpdateListen can now change model/language — exposed additively (see shim below) (deepgram-docs#1066)
  • speaker / speaker_confidence on pre-recorded words (deepgram-docs#1063)
  • ListenV2Redact, retry-backoff tuning, and transparent gzip/deflate (ResponseDecompressionInterceptor)

Back-compat handling for generator-introduced breaks (STOPGAP)

fern-java-sdk 4.16.0 renamed/reshaped public types 0.7.x shipped. These are patched back and frozen; drop once fixed upstream (Fern report pending):

  • Type renames (4.16.0 collision-based name shortening): DeepgramSpeakProviderModel→DeepgramModel, AnthropicThinkProviderModel→AnthropicModel, GoogleThinkProviderModel→GoogleModel, Cartesia*, Groq* — renamed back. (OpenAi* was unaffected — it's the only think+speak provider, so its names never collided.)
  • AgentV1UpdateListenListen.getProvider() widened DeepgramListenProviderV2 → a V1|V2 union. Additive shim: getProvider() still returns DeepgramListenProviderV2 and provider(DeepgramListenProviderV2) still builds; the union is exposed via getProviderValue() and provider(DeepgramListenProviderV1) for the new model/language capability. Regression-tested by AgentV1UpdateListenShimTest.
  • Agent conversation history (ConversationHistoryMessage, FunctionCallHistoryMessage) reparented onto history-specific types with the shared ContextMessagesItem* types deleted — restored to 0.7.x shapes, deleted types re-added (return-type changes can't be shimmed additively in Java).

Patch reconciliation

  • ClientOptions retired from .fernignore — the runtime-version flag is on docs main, and the Maven-coordinate fix is deepgram/deepgram-docs#1069, which is still open. This regen was generated from a branch that includes it, so the headers in this PR are correct, but the unfreeze depends on #1069 landing: #1069 must merge before 0.7.2 is cut, or a later regen from main would restamp the wrong X-Fern-SDK-Name (com.deepgram:deepgram-sdk) with no freeze left to catch it. Added maven-jar-plugin manifest stamping to pom.xml so the published JAR carries Implementation-Version from the release-please-managed <version>.
  • Re-applied clean: ReconnectingWebSocketListener, 11 fields-less hashCode() types, listen/speak WS query-param + additionalProperties + forward-compat patches. listen v2 merge preserves the new redact + sendForceEndTurn.

Verification

  • Unit tests (./gradlew unitTest) — pass, including the new AgentV1UpdateListenShimTest (shim API surface, outbound JSON shape, V1/V2 round-trip) alongside the existing patch guards (RegenTypesTest hashCode, QueryStringMapperTest, connect wire tests, ListenV2/SpeakV2ForwardCompatTest, ReconnectingWebSocketListenerTest, RetryInterceptorTest).
  • Integration tests (./gradlew integrationTest, live API) — pass (transcribe URL/file, speak REST, read analyze, manage projects; invalid-key error handling).
  • Examples — all compile (compileExamples); the safe / changed-area set runs green against the live API.
  • spotlessCheck clean; CI green.

Review follow-ups (added after the initial regen)

  • Version-less agent listen providers were being dropped. version is optional on both provider variants, so {"provider":{"type":"deepgram","model":"nova-3"}} is valid and is what 0.7.x emitted — but Fern's defaultImpl = _UnknownValue sent it to an unknown variant whose value was never populated, so the getter returned null and re-serializing emitted {"provider":null}, silently dropping the provider. Now defaultImpl = V2Value on all three agent listen-provider unions. AgentV1UpdateListenListenProvider is new here so that was a regression; the two Settings unions shipped the same defect in 0.7.1 and are fixed too, so all three agree. Guarded by AgentV1UpdateListenShimTest and the new AgentSettingsProviderDefaultTest.
  • ListenV2ForceEndTurn was missing hashCode() — the only one of twelve fields-less types not carrying the manual patch. Added, frozen, and asserted in RegenTypesTest.
  • The new retry-tuning options were unreachable from DeepgramClient.builder(). initialRetryDelayMillis/maxRetryDelayMillis/retryJitterFactor landed on the parent builder only, so using one mid-chain downgraded the static type and build() returned a DeepgramApiClient. Overridden in both hand-maintained wrappers, matching the existing apiKey/timeout/maxRetries pattern.
  • Freezes added for every newly hand-patched file — the two Settings unions were unfrozen, so the next regen would have reverted them silently.
  • release-please: dropped the now-dead ClientOptions.java entry (the file has no x-release-please-version markers left, so the updater silently no-opped), and added jar-manifest stamping to build.gradle so Package.getImplementationVersion() resolves on the Gradle path too, not just the published Maven artifact.
  • README: documented the backoff knobs and the per-request RequestOptions.maxRetries(...) override. All snippets were compiled against the built SDK — which is how the builder gap above was found.

Gate after these changes: ./gradlew clean unitTest spotlessCheck compileExamples104 tests, 0 failures. Each new guard was checked by reverting its fix and confirming the test fails.

@dg-coreylweathers dg-coreylweathers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — clean pre-regen prep. Verified:

  • All 17 .bak snapshots are byte-identical to the patched originals on main (hash-compared each pair), so the reconciliation source-of-truth is faithful and complete.
  • Unfreeze is complete: no original (non-.bak) path lingers in .fernignore that would silently keep a file frozen.
  • Blast radius is exactly .fernignore + 17 .bak files — no original .java modified/deleted; patches (no_delay escape-hatch + arraysAsRepeats multi-value serialization) still intact on the originals.
  • Permanent freezes untouched; functionally inert (.bak isn't compiled, no withSourcesJar() so nothing leaks to a published artifact).

One optional nit: the .bak files sit under src/main/java/ with no .gitignore coverage — carry a cleanup item into the reconciliation PR to delete them and restore the 17 .fernignore entries to their .java paths.

The real risk lives in the post-regen reconciliation, not here. When Fern overwrites the now-unfrozen originals it drops every manual patch; the .bak snapshots are the only safety net. The deepgram-sdk-review-regen pass must confirm all four patch families survive — especially the no_delay escape-hatch + multi-value WS serialization, plus the Flux oneOf non-breaking reshape (#1064) that the regen source carries. Leaving merge to Greg.

@GregHolmes GregHolmes changed the title chore: SDK regeneration 2026-07-31 chore: regenerate sdk from latest specs 2026-07-31 Jul 31, 2026
@GregHolmes GregHolmes changed the title chore: regenerate sdk from latest specs 2026-07-31 feat!: sdk regeneration 2026-07-31 Jul 31, 2026
…enaming

fern-java-sdk 4.16.0 unconditionally shortens provider type names, renaming
public types that 0.7.x shipped (e.g. DeepgramSpeakProviderModel -> DeepgramModel).
Rename them back and freeze the reverted leaf types + referencing payloads so the
regen is source-compatible. Stopgap until the generator regression is fixed upstream.
- AgentV1UpdateListenListen: additive shim — getProvider() still returns
  DeepgramListenProviderV2 (0.7.x compat) while the new V1|V2 union is exposed via
  getProviderValue()/provider(DeepgramListenProviderV1) for model/language changes (#1066).
- ConversationHistoryMessage / FunctionCallHistoryMessage: restored to 0.7.x shapes and
  re-added the two deleted ContextMessagesItem types (return-type changes can't be shimmed
  additively in Java). Frozen. Stopgap until the new shapes ship in a major.
@GregHolmes GregHolmes changed the title feat!: sdk regeneration 2026-07-31 feat: sdk regeneration 2026-07-31 Jul 31, 2026
@GregHolmes GregHolmes changed the title feat: sdk regeneration 2026-07-31 feat(regen): add diarize_info, Flux force-end-turn, update-listen, word speaker confidence Jul 31, 2026
Adds AgentV1UpdateListenShimTest — verifies the hand-written shim keeps the 0.7.x
typed API (getProvider()/provider(V2)), exposes the union additively
(getProviderValue()/provider(V1)), serializes the provider as the bare object once,
and round-trips both V1 and V2.
`version` is optional on both DeepgramListenProviderV1 and V2, so a provider
object without it is a valid payload -- and is exactly what 0.7.x emitted and
parsed as a v2. Fern points the unions' @JsonTypeInfo defaultImpl at
_UnknownValue, whose @JsonCreator has an empty body, so such a payload
deserialized to an unknown variant carrying null: the provider getter returned
null and re-serializing emitted {"provider":null}, silently dropping the
caller's provider. _getUnknown() and equals() threw NullPointerException.

Measured against the released 0.7.1 jar, same input:

  IN    : {"provider":{"type":"deepgram","model":"nova-3"}}
  0.7.1 : getProvider() = DeepgramListenProviderV2
  before: getProvider() = null,  re-serialize {"provider":null}
  after : getProvider() = DeepgramListenProviderV2

Point defaultImpl at V2Value on all three agent listen-provider unions, which
matches the server's own default and restores 0.7.x behaviour. Jackson applies
defaultImpl for an absent OR unrecognized discriminator, so an unknown future
version now coerces to v2 rather than losing the provider; these messages are
client-sent, so the caller chooses the version. This leaves _isUnknown() and
_getUnknown() unreachable on these types.

AgentV1UpdateListenListenProvider is new in the 4.16.0 regen, so that one was a
regression. The two Settings unions shipped with the same defect in 0.7.1 and
are patched too, so all three behave consistently.
Fern emits equals() (all instances of a fields-less message are equal) but no
hashCode(), violating the Object contract: two equal instances hash differently,
so a HashSet built from one does not contain the other.

ListenV2ForceEndTurn is new in this regen and was the only one of twelve
fields-less types left unpatched -- the other eleven already carry the manual
hashCode(), are frozen, and are asserted by RegenTypesTest. Bring it in line and
add it to the existing contract assertion.
The regen added initialRetryDelayMillis, maxRetryDelayMillis and
retryJitterFactor to DeepgramApiClientBuilder only. Those return the parent
type, so using one mid-chain downgraded the static type and build() yielded a
DeepgramApiClient:

  DeepgramClient client = DeepgramClient.builder()
      .apiKey("k")
      .initialRetryDelayMillis(500)  // returns the parent type from here on
      .build();                      // error: DeepgramApiClient -> DeepgramClient

The hand-maintained wrappers already override apiKey/timeout/maxRetries and
friends for exactly this reason; the new methods just were not added. Override
all three in both the sync and async wrappers.

Worth a checklist item on future regens: when the generated parent builder gains
public methods, our frozen wrappers go stale silently -- nothing fails until a
consumer tries the fluent chain.
Freeze the three patched agent listen-provider unions and ListenV2ForceEndTurn so
the fixes survive the next regen, and record each one in the temporarily-frozen
list in AGENTS.md with the reason and the unfreeze condition.

The two Settings provider unions were not frozen before, so without this the
next regen would have silently reverted them.
… entry

ClientOptions no longer carries x-release-please-version markers -- the regen
replaced the hardcoded version strings with a manifest lookup (runtime-version:
true), so the release-please "generic" updater had nothing left to rewrite in
that file and silently no-opped. Remove the entry rather than leave it looking
like that file's version is release-managed.

The version now resolves via Package.getImplementationVersion(). pom.xml already
stamped the manifest for the published artifact (mvn deploy); add the same to the
Gradle jar task so both build paths carry a real Implementation-Version and the
hardcoded fallback in ClientOptions stays unreachable in practice.
The Retry Configuration section showed only maxRetries while this release adds
three backoff knobs and a per-request RequestOptions.maxRetries override. Note
which statuses are retried, and show both. All snippets compile against the SDK.

@dg-coreylweathers dg-coreylweathers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — full Fern 4.16.0 regeneration review (this supersedes the earlier prep-PR approval that was auto-dismissed when the head moved).

Independently verified (build gate run in Docker, not trusting CI):

  • ./gradlew clean unitTest spotlessCheck compileExamples -> BUILD SUCCESSFUL, 104 tests, 0 failures; all new guard tests ran (shim, provider-default, regen-types hashCode, additionalProperties wire, forward-compat).
  • Source-compat with 0.7.x: 0 removed/renamed public-type files vs v0.7.1; compileExamples (real usage code) green corroborates the surface.
  • All 3 documented shims present and correct: type-rename reversal (short-named orphans not in tree), additive UpdateListen union shim, conversation-history reparent restored.
  • Version-less provider drop fixed (defaultImpl=V2Value on all 3 agent listen-provider unions).
  • hashCode on all 12 fields-less types incl. ListenV2ForceEndTurn; retry-tuning options reachable from both wrapper builders.
  • no_delay escape hatch survived: wire test asserts it lands in the real upgrade URL on all 4 WS clients.
  • New freezes complete + documented; .bak prep leftovers cleaned up; ClientOptions headers correct.

Two conditions, both about the RELEASE not the merge (details in Slack):

  1. Merge preserving the fix: commits (not squash-as-chore, or release-please cuts nothing) + add a 0.7.2 changelog stanza for the new features (diarize_info, speaker_confidence, force-end-turn, redact, gzip) so the release isn't undersold.
  2. Land docs #1069 (one line) so the now-unfrozen ClientOptions doesn't restamp the wrong Maven coordinate on the next regen. Order vs this PR doesn't matter for today's artifact; #1069 just must land before the next regen-from-main.

Cutting 0.7.2 today is safe: release CI does mvn deploy from committed source (no regen), and the correct headers are already committed here.

@GregHolmes
GregHolmes merged commit 5b6323a into main Jul 31, 2026
9 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.

2 participants