Skip to content
Merged
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
7 changes: 4 additions & 3 deletions .fern/metadata.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
{
"cliVersion": "5.44.6",
"generatorName": "fernapi/fern-java-sdk",
"generatorVersion": "4.10.1",
"generatorVersion": "4.16.0",
"generatorConfig": {
"package-prefix": "com.deepgram",
"base-api-exception-class-name": "DeepgramHttpException",
"enable-forward-compatible-enums": true,
"client": {
"class-name": "DeepgramClient"
},
"enable-wire-tests": true
"enable-wire-tests": true,
"runtime-version": true
},
"originGitCommit": "ff8fd2b74fdd5c081e9f111d59d3619f7e286dd8",
"originGitCommit": "03f06776bbb692c49f8d76c4230bca7f4bc4bca7",
"originGitCommitIsDirty": true,
"invokedBy": "manual",
"sdkVersion": "0.7.1"
Expand Down
11 changes: 11 additions & 0 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ src/main/java/com/deepgram/resources/agent/v1/types/AgentV1KeepAlive.java
src/main/java/com/deepgram/resources/agent/v1/types/AgentV1ThinkUpdated.java
src/main/java/com/deepgram/resources/agent/v1/types/AgentV1PromptUpdated.java

# Union default-variant fix (STOPGAP). The agent listen-provider unions declare `version` as an
# optional discriminator, so a provider payload without it is valid (and is what 0.7.x emits). 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 caller's provider on the wire. Patched to
# defaultImpl = V2Value on each. Guarded by AgentSettingsProviderDefaultTest. Unfreeze and drop once
# the generator stops defaulting unions to the empty _UnknownValue (tracked as an upstream Fern request).
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

# Build and project configuration
build.gradle
settings.gradle
Expand Down
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ 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
- `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`. 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/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).
- 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/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}.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).
- 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).

### Prepare repo for regeneration

Expand Down
46 changes: 45 additions & 1 deletion 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.6 to v0.7](./docs/Migrating-v0.6-to-v0.7.md) (current)
- [v0.7 to v0.8](./docs/Migrating-v0.7-to-v0.8.md) (current)
- [v0.6 to v0.7](./docs/Migrating-v0.6-to-v0.7.md)
- [v0.5 to v0.6](./docs/Migrating-v0.5-to-v0.6.md)
- [v0.3 to v0.4](./docs/Migrating-v0.3-to-v0.4.md)
- [v0.2 to v0.3](./docs/Migrating-v0.2-to-v0.3.md)
Expand Down Expand Up @@ -332,6 +333,49 @@ ttsWs.sendClose(SpeakV1Close.builder()
ttsWs.close();
```

### Flux TTS Barge-in (Speak V2 WebSocket)

The Speak V2 WebSocket adds Flux TTS barge-in and mid-stream controls. Open the connection with `V2ConnectOptions` (model required; `speed` and `expressivity` are optional connect params), then:

- **`sendConfigure(...)`** adjusts the speech-rate multiplier mid-stream. Accepted speeds are `0.85`–`1.15` in `0.05` steps; the server replies via `onConfigureSuccess` or a typed `onConfigureFailure` (e.g. `SPEED_OUT_OF_RANGE`).
- **`sendInterrupt(...)`** stops playback (barge-in). Pass a `SpeakV2InterruptPlaybackOffset` with the audio milliseconds played so the `onSpeechInterrupted` event can report `getTextSpoken()` / `getTextRemaining()`. The offset is cumulative from session start, and each interrupt must advance past the previous one.

```java
import com.deepgram.resources.speak.v2.types.SpeakV2Configure;
import com.deepgram.resources.speak.v2.types.SpeakV2Interrupt;
import com.deepgram.resources.speak.v2.types.SpeakV2InterruptPlaybackOffset;
import com.deepgram.resources.speak.v2.types.SpeakV2Speak;
import com.deepgram.resources.speak.v2.websocket.V2ConnectOptions;
import com.deepgram.resources.speak.v2.websocket.V2WebSocketClient;

V2WebSocketClient ttsWs = client.speak().v2().v2WebSocket();

// Mid-stream configure acknowledgements
ttsWs.onConfigureSuccess(success -> System.out.println("configured: " + success.getApplied()));
ttsWs.onConfigureFailure(failure ->
System.out.println("rejected [" + failure.getCode() + "]: " + failure.getDescription()));

// Barge-in: reports where playback was cut off when the interrupt carried a playback offset
ttsWs.onSpeechInterrupted(interrupted -> {
interrupted.getTextSpoken().ifPresent(spoken -> System.out.println("spoken: " + spoken));
interrupted.getTextRemaining().ifPresent(remaining -> System.out.println("remaining: " + remaining));
});

ttsWs.connect(V2ConnectOptions.builder().model("flux-alexis-en").build()).get(10, TimeUnit.SECONDS);

ttsWs.sendConfigure(SpeakV2Configure.builder().speed(1.05).build());
ttsWs.sendSpeak(SpeakV2Speak.builder().text("This is a longer sentence we can barge in on.").build());

// Stop playback after ~1.2s of audio has played
ttsWs.sendInterrupt(SpeakV2Interrupt.builder()
.playbackOffset(SpeakV2InterruptPlaybackOffset.builder().value(1200).build())
.build());

ttsWs.close();
```

See [`examples/speak/StreamingTtsV2.java`](examples/speak/StreamingTtsV2.java) for a complete, runnable barge-in example.

### Agent WebSocket

Connect to Deepgram's voice agent for real-time conversational AI.
Expand Down
Loading
Loading