Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .fern/metadata.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"cliVersion": "5.95.1",
"generatorName": "fernapi/fern-java-sdk",
"generatorVersion": "4.21.0",
"generatorVersion": "4.23.1",
"generatorConfig": {
"package-prefix": "com.deepgram",
"base-api-exception-class-name": "DeepgramHttpException",
Expand All @@ -12,8 +12,8 @@
"enable-wire-tests": true,
"runtime-version": true
},
"originGitCommit": "f6f5d3876c8996e2a6b6e59136bb222183a8e317",
"originGitCommit": "e252995bcdb25f3e12d46ae342a2b93d0c1085f9",
"originGitCommitIsDirty": true,
"invokedBy": "manual",
"sdkVersion": "0.10.2"
}
"sdkVersion": "0.10.3"
}
8 changes: 2 additions & 6 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ src/main/java/com/deepgram/AsyncDeepgramClientBuilder.java
# Contains User-Agent, X-Fern-SDK-Name, and X-Fern-SDK-Version headers
# with // x-release-please-version comments for automated version bumps.
# Fern regen overwrites these with incorrect SDK names and strips the markers.
# Fern 4.21.0 owns the OkHttp lifecycle behavior; retain it while reapplying only these headers.
# Fern 4.22.1 closes tracked WebSockets before SDK-owned OkHttp resources; retain that lifecycle behavior while
# reapplying only these headers.
src/main/java/com/deepgram/core/ClientOptions.java

# Transport abstraction (pluggable transport for SageMaker, etc.)
Expand Down Expand Up @@ -51,11 +52,6 @@ src/main/java/com/deepgram/resources/listen/v2/websocket/V2WebSocketClient.java
src/main/java/com/deepgram/resources/listen/v1/websocket/V1WebSocketClient.java
src/main/java/com/deepgram/resources/speak/v1/websocket/V1WebSocketClient.java

# Close is safe before connect in every generated WebSocket client. The listener is created only
# during connect(), so disconnect() must tolerate a null listener for try-with-resources clients.
# Remove these patches once Fern emits the null guard.
src/main/java/com/deepgram/resources/agent/v1/websocket/V1WebSocketClient.java

# Restores the FLUX_RENEE_EN constant that generator 4.18.0 dropped. The voice is live:
# POST /v2/speak?model=flux-renee-en returns 200 with valid audio, and the name resolves in the
# server's model registry (an invented flux-* name is rejected with INVALID_QUERY_PARAMETER), so the
Expand Down
3 changes: 1 addition & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,10 @@ How to identify:

Current temporarily frozen files:

- `src/main/java/com/deepgram/core/ClientOptions.java` - preserves release-please version markers and correct SDK header constants that Fern currently overwrites; use the standard `.bak` swap/restore workflow during regen review. Since generator 4.18.0 Fern emits a `getSdkVersion()` helper reading `Package.getImplementationVersion()` instead of a literal. That *does* resolve in the published artifact (CI publishes via `mvn deploy -P release`, and `pom.xml`'s maven-jar-plugin sets `addDefaultImplementationEntries=true`, so the JAR manifest carries `Implementation-Version`), but it resolves to `null` under Gradle and in tests, where it silently falls back to a hardcoded literal the generator does not keep current. We keep the explicit literals because they are correct in every context and because `.github/release-please-config.json` already lists this file in `extra-files`, so release-please bumps it alongside `pom.xml`, `build.gradle`, and `.fern/metadata.json`. Fern also emits `User-Agent` with a `com.deepgram.` prefix while leaving `X-Fern-SDK-Name` on the `com.deepgram:` Maven-coordinate form; we keep both on the colon form. Fern 4.21.0 generates `AutoCloseable` root clients and ownership-aware OkHttp cleanup; the permanent custom client wrappers inherit it, so do not add wrapper-local lifecycle code and retain Fern's lifecycle implementation during reconciliation.
- `src/main/java/com/deepgram/core/ClientOptions.java` - preserves release-please version markers and correct SDK header constants that Fern currently overwrites; use the standard `.bak` swap/restore workflow during regen review. Since generator 4.18.0 Fern emits a `getSdkVersion()` helper reading `Package.getImplementationVersion()` instead of a literal. That *does* resolve in the published artifact (CI publishes via `mvn deploy -P release`, and `pom.xml`'s maven-jar-plugin sets `addDefaultImplementationEntries=true`, so the JAR manifest carries `Implementation-Version`), but it resolves to `null` under Gradle and in tests, where it silently falls back to a hardcoded literal the generator does not keep current. We keep the explicit literals because they are correct in every context and because `.github/release-please-config.json` already lists this file in `extra-files`, so release-please bumps it alongside `pom.xml`, `build.gradle`, and `.fern/metadata.json`. Fern also emits `User-Agent` with a `com.deepgram.` prefix while leaving `X-Fern-SDK-Name` on the `com.deepgram:` Maven-coordinate form; we keep both on the colon form. Fern 4.22.1 tracks and closes child WebSockets before shutting down SDK-owned OkHttp resources; the permanent custom client wrappers inherit it, so do not add wrapper-local lifecycle code and retain Fern's lifecycle implementation during reconciliation.
- `src/main/java/com/deepgram/core/ReconnectingWebSocketListener.java` - carries bug fixes for `maxRetries(0)` semantics ("connect once, don't retry") and a configurable `connectionTimeoutMs` field (was hardcoded 4000ms), plus an `applyOptionsOverride(...)` hook used by `TransportWebSocketFactory` to apply per-transport reconnect policy; pull this back out once the fixes are upstreamed into the Fern generator. Use the standard `.bak` swap/restore workflow during regen review.
- `src/main/java/com/deepgram/resources/speak/v2/websocket/V2WebSocketClient.java` and `src/main/java/com/deepgram/resources/listen/v2/websocket/V2WebSocketClient.java` - forward-compat patch (both clients). Fern's generated `handleIncomingMessage` dispatcher routes any unrecognized message type to `onError` with "Update your SDK version...", which makes a benign new server control frame look fatal to a deployed client. Patched so the unrecognized-type branch is a no-op — the raw frame is already delivered via `onMessage(String)` earlier in the method, so consumers still see it. Mirrors the JS/Python SDKs' forward-compat behavior and is regression-guarded by `src/test/java/com/deepgram/SpeakV2ForwardCompatTest.java` and `src/test/java/com/deepgram/ListenV2ForwardCompatTest.java`. These two clients also carry the streaming query-param patches described in the next entry. Use the standard `.bak` swap/restore workflow during regen review; re-apply the no-op to both after regen, and unfreeze once the generator stops treating unknown frames as errors.
- `src/main/java/com/deepgram/resources/listen/v1/websocket/V1WebSocketClient.java` and `src/main/java/com/deepgram/resources/speak/v1/websocket/V1WebSocketClient.java` (and the v2 clients above) - streaming query-param patches on the generated `connect()` builders. Two fixes: (1) multi-value serialization — array-valued params (listen: `keyterm`, `keywords`, `replace`, `search`, `tag`, `extra`, `language_hint`; speak: `tag`) were serialized with `String.valueOf(union.get())`, collapsing a `List` into one param (`keyterm=[a, b]`) instead of repeats (`keyterm=a&keyterm=b`); (2) an `additionalProperties` escape hatch — the builder exposes `additionalProperty(key, value)` for unmodeled params (e.g. `no_delay`) but `connect()` never emitted them to the URL. Both patched to route through `QueryStringMapper(arraysAsRepeats=true)`, matching the REST path. Use the standard `.bak` swap/restore workflow during regen review; re-apply after regen and unfreeze once the generator emits array params as repeats and serializes `additionalProperties` on the WS `connect()` path (tracked as an upstream Fern request).
- All five generated WebSocket clients, including `src/main/java/com/deepgram/resources/agent/v1/websocket/V1WebSocketClient.java`, carry a `disconnect()` null guard so `close()` is safe before `connect()`. This keeps `AutoCloseable` safe for try-with-resources; re-apply the guards and retain the `.fernignore` entry until Fern emits them.
- Fields-less message types carrying a manual `hashCode()` patch (Fern generates `equals()` but no `hashCode()` for these, violating the Object contract): `src/main/java/com/deepgram/resources/listen/v2/types/ListenV2CloseStream.java`, `src/main/java/com/deepgram/resources/listen/v2/types/ListenV2ForceEndTurn.java`, `src/main/java/com/deepgram/resources/speak/v2/types/SpeakV2Close.java`, `src/main/java/com/deepgram/resources/speak/v2/types/SpeakV2Flush.java`, and the `AgentV1*` event types `src/main/java/com/deepgram/resources/agent/v1/types/{AgentV1ListenUpdated,AgentV1SpeakUpdated,AgentV1AgentAudioDone,AgentV1SettingsApplied,AgentV1UserStartedSpeaking,AgentV1KeepAlive,AgentV1ThinkUpdated,AgentV1PromptUpdated,AgentV1ForceEndTurn}.java`. Use the standard `.bak` swap/restore workflow during regen review; drop the patches and unfreeze all of them once the generator emits a matching equals/hashCode pair for fields-less types (tracked as an upstream Fern request).
- `src/main/java/com/deepgram/types/DeepgramModel.java` - restores the `FLUX_RENEE_EN` constant that generator 4.18.0 dropped. The voice is live: `POST /v2/speak?model=flux-renee-en` returns 200 with valid audio, and the name resolves in the server's model registry (an invented `flux-*` name is rejected with `INVALID_QUERY_PARAMETER`), so the removal is a spec regression rather than a retirement, and dropping the constant would break 0.8.0 callers for nothing. Five touchpoints: the constant, the `Value` enum entry, the `visit()` case, the `valueOf()` case, and the `Visitor` method. **This file is unlike the other temporarily frozen ones — it receives frequent additive spec changes (4.18.0 alone added 25 constants), so on the next regen do NOT restore the `.bak` wholesale.** Diff the `.bak` against the newly generated file, carry forward every new voice, and re-apply only the `FLUX_RENEE_EN` touchpoints. Drop the patch and unfreeze once the spec lists the voice again (tracked as an upstream spec request).
- Union default-variant fix on the agent listen-provider unions: `src/main/java/com/deepgram/resources/agent/v1/types/AgentV1UpdateListenListenProvider.java`, `src/main/java/com/deepgram/resources/agent/v1/types/AgentV1SettingsAgentListenProvider.java`, `src/main/java/com/deepgram/resources/agent/v1/types/AgentV1SettingsAgentContextListenProvider.java`. `version` is an optional discriminator, so a provider payload without it is valid (and is what 0.7.x emits), but Fern points `@JsonTypeInfo` `defaultImpl` at the empty-bodied `_UnknownValue`, so such a payload deserializes to an unknown variant carrying `null` — `getProvider()` returns `null` and re-serialization emits `{"provider":null}`, silently dropping the provider on the wire. Patched to `defaultImpl = V2Value` on each; guarded by `src/test/java/com/deepgram/AgentSettingsProviderDefaultTest.java`. Use the standard `.bak` swap/restore workflow during regen review; drop the patches and unfreeze once the generator stops defaulting unions to the empty `_UnknownValue` (tracked as an upstream Fern request).
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ You can learn more about the Deepgram API at [developers.deepgram.com](https://d

### Migrating Between Versions

- [v0.9 to v0.10](./docs/Migrating-v0.9-to-v0.10.md) (current)
- [v0.10 to v0.11](./docs/Migrating-v0.10-to-v0.11.md) (current)
- [v0.9 to v0.10](./docs/Migrating-v0.9-to-v0.10.md)
- [v0.8 to v0.9](./docs/Migrating-v0.8-to-v0.9.md)
- [v0.7 to v0.8](./docs/Migrating-v0.7-to-v0.8.md)
- [v0.6 to v0.7](./docs/Migrating-v0.6-to-v0.7.md)
Expand Down Expand Up @@ -70,9 +71,9 @@ Get your API key from the [Deepgram Console](https://console.deepgram.com/).

### Resource Lifecycle

Close an SDK-created client when your application is finished with it. This releases the OkHttp dispatcher and
connection pool. Close each WebSocket client before closing its root client; root-client cleanup does not close active
WebSocket clients for you.
Close an SDK-created client when your application is finished with it. This disconnects any WebSocket clients still
connected through it, then releases the OkHttp dispatcher and connection pool. Close an individual WebSocket client
earlier when its work is complete; after the root client closes, new WebSocket connections fail.

```java
import com.deepgram.DeepgramClient;
Expand Down
93 changes: 93 additions & 0 deletions docs/Migrating-v0.10-to-v0.11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# v0.10 to v0.11 Migration Guide

This guide covers the breaking source changes in Deepgram Java SDK `0.11.0`. The release corrects the shared Topics and Intents response shape, adds a Speak V2 Configure failure code, and includes Fern retry behavior updates. It also adds Flux TTS Controls support.

## Update the dependency

Upgrade to `0.11.0` with Gradle or Maven.

**Gradle**

```groovy
dependencies {
implementation 'com.deepgram:deepgram-java-sdk:0.11.0'
}
```

**Maven**

```xml
<dependency>
<groupId>com.deepgram</groupId>
<artifactId>deepgram-java-sdk</artifactId>
<version>0.11.0</version>
</dependency>
```

## Topics and Intents segments

`SharedTopics` and `SharedIntents` now expose their segments directly. The previous generated models reflected an extra `results.topics` or `results.intents` wrapper that is not present in the API payload.

| Old path | New path |
| --- | --- |
| `SharedTopics.getResults().get().getTopics().get().getSegments()` | `SharedTopics.getSegments()` |
| `SharedIntents.getResults().get().getIntents().get().getSegments()` | `SharedIntents.getSegments()` |
| `SharedTopicsResults` | Removed; access segments through `SharedTopics.getSegments()` |
| `SharedTopicsResultsTopics` | Removed; access segments through `SharedTopics.getSegments()` |
| `com.deepgram.types.SharedTopicsResultsTopicsSegmentsItem` | `com.deepgram.types.SharedTopicsSegmentsItem` |
| `com.deepgram.types.SharedTopicsResultsTopicsSegmentsItemTopicsItem` | `com.deepgram.types.SharedTopicsSegmentsItemTopicsItem` |
| `SharedIntentsResults` | Removed; access segments through `SharedIntents.getSegments()` |
| `SharedIntentsResultsIntents` | Removed; access segments through `SharedIntents.getSegments()` |
| `com.deepgram.types.SharedIntentsResultsIntentsSegmentsItem` | `com.deepgram.types.SharedIntentsSegmentsItem` |
| `com.deepgram.types.SharedIntentsResultsIntentsSegmentsItemIntentsItem` | `com.deepgram.types.SharedIntentsSegmentsItemIntentsItem` |

For example, replace the old Topics traversal:

```java
List<SharedTopicsResultsTopicsSegmentsItem> segments = topics.getResults().get()
.getTopics().get()
.getSegments().get();
```

with:

```java
List<SharedTopicsSegmentsItem> segments = topics.getSegments().get();
```

Make the equivalent replacement for `SharedIntents` and its segment item type.

## Speak V2 Configure failure visitor

`SpeakV2ConfigureFailureCode` now includes `CONTROL_COMBINATION_INVALID`. Implementations of `SpeakV2ConfigureFailureCode.Visitor<T>` must add `visitControlCombinationInvalid()`.

```java
SpeakV2ConfigureFailureCode.Visitor<String> visitor = new SpeakV2ConfigureFailureCode.Visitor<>() {
@Override
public String visitControlCombinationInvalid() {
return "Change the conflicting Controls configuration.";
}

// Implement the remaining visitor methods.
};
```

## Retry behavior

Fern `4.21.2` and `4.22.2` change retry behavior for the SDK-created OkHttpClient without changing the public client-builder API.

- The configured HTTP timeout is now applied to each attempt, rather than to the full retry loop. A request can therefore take longer than its configured timeout when retries and backoff occur.
- Before retrying a retryable HTTP response, the SDK buffers that response. If a later retry fails with a transport error, the SDK returns the earlier HTTP response instead of discarding its status, headers, and body.

The tradeoffs are intentional: requests can occupy a caller for longer, and buffering holds a retryable response body in memory, but callers retain the actionable API error that triggered the retry instead of only observing a later connection failure. Set explicit timeouts and retry limits appropriate for latency-sensitive or large-response workloads, and continue to inspect returned HTTP errors during incident handling. Clients built with `.httpClient(...)` retain the caller-supplied retry policy, but the SDK still adds its logging and decompression interceptors. Setting `.timeout(...)` also overrides that client's call timeout.

## Flux TTS Controls

Flux TTS now supports inline Controls for speed, pauses, and pronunciation overrides. Controls are additive: batch requests use `SpeakV2Request.speed(...)` for speed and `SpeakV2Request.text(...)` for pause and pronunciation markers. Streaming requests use `V2ConnectOptions.speed(...)` or `SpeakV2Configure.speed(...)` for speed and `SpeakV2Speak.text(...)` for pronunciation controls; a pause marker on a streaming request fails with `DATA-0002`.

```java
String pause = "\\{pause:500ms\\}";
String pronunciation = "\\{\"word\": \"dupilumab\", \"pronounce\": \"duːˈpɪljuːmæb\"\\}";
```

Pronunciation controls are Early Access. On batch requests, pronunciation cannot be combined with a non-default speed or with a pause; the API returns HTTP 400 with `CONTROL_COMBINATION_INVALID`. On streaming requests, a pause marker or a pronunciation control with a non-default speed emits `DATA-0002` and closes the WebSocket. A mid-stream `Configure` that changes speed while a buffered turn contains a pronunciation control returns `ConfigureFailure` with `CONTROL_COMBINATION_INVALID`. The Flux TTS Controls guide publishes with the Controls release; consult that guide for supported syntax and availability once it is live.
Loading
Loading