@breeze.blue/sdk 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +140 -28
- package/dist/client.d.ts +102 -1
- package/dist/client.js +946 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/types.d.ts +69 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
- Added opt-in `textToSpeech.realtime.connectManaged(...)` for long logical
|
|
6
|
+
conversations. It derives session keepalive from `session.ready`, rotates
|
|
7
|
+
bounded physical WebSockets at turn boundaries, obtains fresh session
|
|
8
|
+
credentials for every epoch, and performs bounded jittered reconnects while
|
|
9
|
+
idle without replaying active turns. Replacement creation and retry delays
|
|
10
|
+
are cancellable,
|
|
11
|
+
and planned rotations briefly drain outstanding `usage.committed` events
|
|
12
|
+
from the old epoch without blocking the next turn.
|
|
13
|
+
- Managed heartbeat now requires a timely server response, so a half-open idle
|
|
14
|
+
WebSocket is replaced with fresh credentials instead of accepting the next
|
|
15
|
+
turn. Active turns still fail as `TURN_INTERRUPTED` and are never replayed.
|
|
16
|
+
Physical epochs also become eligible for turn-boundary rotation after 10
|
|
17
|
+
minutes by default, independently of a longer server-advertised deadline.
|
|
18
|
+
An active turn can delay the switch; both safety windows are configurable.
|
|
19
|
+
- Aligned managed realtime error handling with protocol semantics: terminal
|
|
20
|
+
auth, billing, and policy failures are not retried; recoverable turn errors
|
|
21
|
+
stay on the same socket; rejected concurrency admission clears the local
|
|
22
|
+
pending turn; transient 408, 425, 429, and 5xx replacement-session failures
|
|
23
|
+
use the bounded reconnect budget; a new turn on the healthy old epoch wins
|
|
24
|
+
even when an in-flight planned candidate fails; and active-turn transport
|
|
25
|
+
failures remain non-replayed. Shared upstream
|
|
26
|
+
`GENERATION_CAPACITY_EXCEEDED` waits for the corresponding
|
|
27
|
+
`turn.cancelled` and keeps the logical session usable.
|
|
28
|
+
- Added typed `session.expiring` and realtime expiry fields. Managed browser
|
|
29
|
+
callers can provide a `sessionFactory` that fetches a fresh client secret
|
|
30
|
+
from their own backend for every physical connection.
|
|
31
|
+
- Fixed the realtime `audio()` iterator so server errors and abnormal closes
|
|
32
|
+
throw `BreezeBlueRealtimeError` instead of ending silently, and preserved
|
|
33
|
+
close-code semantics when a WebSocket `error` event arrives just before its
|
|
34
|
+
`close` event.
|
|
35
|
+
|
|
36
|
+
## 0.5.1
|
|
37
|
+
|
|
38
|
+
- Added official voice publishing metadata to `voices.savePreview(...)` and
|
|
39
|
+
`voices.edit(...)`, including `primaryCategoryCode`, `visibility`, and the
|
|
40
|
+
typed `SavedVoice` response.
|
|
41
|
+
- Aligned voice, history, and generation metadata with the public API by using
|
|
42
|
+
`origin` instead of the legacy category fields; voice search now accepts an
|
|
43
|
+
`origin` filter.
|
|
44
|
+
- Made `voices.edit(...)` support metadata-only updates without requiring a
|
|
45
|
+
voice name.
|
|
46
|
+
- Improved the realtime TTS example to start consuming before sending text and
|
|
47
|
+
continue until `turn.done`, so early audio is not missed.
|
|
48
|
+
|
|
3
49
|
## 0.5.0
|
|
4
50
|
|
|
5
51
|
- Fixed `textToSpeech.realtime.connect(...)` so a failed WebSocket handshake
|
package/README.md
CHANGED
|
@@ -112,29 +112,35 @@ Realtime needs a `WebSocket` implementation. Browsers, edge runtimes, and
|
|
|
112
112
|
Node 22+ provide a global one; on Node 20, pass a constructor (for example the
|
|
113
113
|
`ws` package's `WebSocket`) via `new BreezeBlueClient({ webSocket })`.
|
|
114
114
|
|
|
115
|
+
Start consuming before appending text. Audio can arrive after `flush()` and may
|
|
116
|
+
continue after `endTurn()`; keep the single consumer running until `turn.done`.
|
|
117
|
+
|
|
115
118
|
```ts
|
|
116
119
|
const connection = await client.textToSpeech.realtime.connect("voc_...", {
|
|
117
|
-
modelId: "
|
|
120
|
+
modelId: "breeze-tts-2",
|
|
118
121
|
});
|
|
119
122
|
|
|
123
|
+
const pcmChunks: Uint8Array[] = [];
|
|
124
|
+
const consumer = (async () => {
|
|
125
|
+
for await (const message of connection) {
|
|
126
|
+
if (message.type === "audio") {
|
|
127
|
+
// Forward this chunk to your playback or transport layer immediately.
|
|
128
|
+
pcmChunks.push(message.audio);
|
|
129
|
+
} else if (message.type === "error") {
|
|
130
|
+
throw new Error(`Realtime TTS failed: ${message.code}: ${message.message}`);
|
|
131
|
+
} else if (message.type === "turn.done") {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
throw new Error("Realtime session closed before turn.done");
|
|
136
|
+
})();
|
|
137
|
+
|
|
120
138
|
connection.startTurn("turn_1");
|
|
121
139
|
connection.appendText("Hello from Breeze.");
|
|
122
140
|
connection.flush();
|
|
123
141
|
connection.endTurn();
|
|
124
142
|
|
|
125
|
-
|
|
126
|
-
for await (const message of connection) {
|
|
127
|
-
if (message.type === "audio") {
|
|
128
|
-
pcmChunks.push(message.audio);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (message.type === "error") {
|
|
132
|
-
throw new Error(`Realtime TTS failed: ${message.code}: ${message.message}`);
|
|
133
|
-
}
|
|
134
|
-
if (message.type === "turn.done") {
|
|
135
|
-
break; // all audio for this turn has been delivered
|
|
136
|
-
}
|
|
137
|
-
}
|
|
143
|
+
await consumer;
|
|
138
144
|
connection.close();
|
|
139
145
|
```
|
|
140
146
|
|
|
@@ -142,33 +148,98 @@ Always consume the connection (or its `audio()` / `events()` iterators) while a
|
|
|
142
148
|
turn is active, and call `close()` when you are done. When the SDK detects a
|
|
143
149
|
connection failure — an invalid server frame, or more than 16 MiB of messages
|
|
144
150
|
piling up unconsumed — it closes the connection and the iterator rejects with
|
|
145
|
-
a `BreezeBlueRealtimeError`.
|
|
151
|
+
a `BreezeBlueRealtimeError`. The `audio()` helper also throws
|
|
152
|
+
`BreezeBlueRealtimeError` for server `error` events and abnormal WebSocket
|
|
153
|
+
closes instead of silently ending.
|
|
146
154
|
|
|
147
155
|
Events are a typed discriminated union (`session.ready`, `turn.started`,
|
|
148
156
|
`audio.started`, `turn.done`, `turn.cancelled`, `usage.committed`,
|
|
149
|
-
`session.closed`, `error`, `pong`), with camelCase fields
|
|
150
|
-
`historyItemId`, and `ttfaMs`. Treat the union as
|
|
151
|
-
may add event types, and the SDK delivers unknown
|
|
152
|
-
ignore event types you do not recognize instead of
|
|
157
|
+
`session.expiring`, `session.closed`, `error`, `pong`), with camelCase fields
|
|
158
|
+
such as `turnId`, `historyItemId`, `expiresAt`, and `ttfaMs`. Treat the union as
|
|
159
|
+
non-exhaustive: the server may add event types, and the SDK delivers unknown
|
|
160
|
+
JSON events unchanged — ignore event types you do not recognize instead of
|
|
161
|
+
switching exhaustively.
|
|
153
162
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
163
|
+
Send a keepalive ping inside the session's `inactivityTimeoutSeconds` window;
|
|
164
|
+
the server answers with a `pong` event. Keep it running during active turns too:
|
|
165
|
+
a long TTFA or upstream stall with no audio does not pause the idle deadline.
|
|
157
166
|
|
|
158
167
|
```ts
|
|
159
|
-
const keepalive = setInterval(() => connection.ping(),
|
|
168
|
+
const keepalive = setInterval(() => connection.ping(), 10_000);
|
|
160
169
|
// ... run turns ...
|
|
161
170
|
clearInterval(keepalive);
|
|
162
171
|
connection.close();
|
|
163
172
|
```
|
|
164
173
|
|
|
174
|
+
For a long logical conversation, use the opt-in managed connection. It derives
|
|
175
|
+
a safe keepalive interval from `session.ready` and requires a server response
|
|
176
|
+
after each ping. A missing acknowledgement replaces an idle half-open socket;
|
|
177
|
+
if a turn is active, it reports `TURN_INTERRUPTED` and never replays commands.
|
|
178
|
+
The manager also marks a physical WebSocket for turn-boundary rotation after
|
|
179
|
+
10 minutes by default (or earlier when the server deadline requires it). An
|
|
180
|
+
active turn can delay the switch beyond that threshold; the server-advertised
|
|
181
|
+
hard lifetime still applies. The manager
|
|
182
|
+
performs up to three unexpected idle reconnect attempts per interruption with
|
|
183
|
+
fresh sessions and jittered exponential backoff:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
const connection = await client.textToSpeech.realtime.connectManaged("voc_...", {
|
|
187
|
+
modelId: "breeze-tts-2",
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const consumer = (async () => {
|
|
191
|
+
for await (const message of connection) {
|
|
192
|
+
if (message.type === "audio") {
|
|
193
|
+
// Play or forward this PCM chunk immediately.
|
|
194
|
+
} else if (message.type === "session.ready") {
|
|
195
|
+
// A new physical epoch is ready; the logical connection remains the same.
|
|
196
|
+
} else if (message.type === "turn.done") {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
})();
|
|
201
|
+
|
|
202
|
+
await connection.startTurnWhenReady("turn_1");
|
|
203
|
+
connection.appendText("Hello from a long-running conversation.");
|
|
204
|
+
connection.endTurn();
|
|
205
|
+
await consumer;
|
|
206
|
+
connection.close();
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Use `heartbeatTimeoutMs` to tune the acknowledgement deadline and
|
|
210
|
+
`maxPhysicalSessionMs` to tune the client-side epoch cap. Set
|
|
211
|
+
`maxPhysicalSessionMs: 0` only when you intentionally want to rely solely on
|
|
212
|
+
the server-advertised deadline.
|
|
213
|
+
|
|
214
|
+
When an idle reconnect is handled successfully, the logical iterator stays
|
|
215
|
+
open, suppresses the replaced physical socket's terminal event, and emits the
|
|
216
|
+
new epoch's `session.ready`. The replacement sends its first heartbeat
|
|
217
|
+
immediately and resumes the derived cadence after an inbound acknowledgement.
|
|
218
|
+
Reconnect attempts are bounded per interruption. `startTurnWhenReady(...)`
|
|
219
|
+
waits only when one of these idle replacements is already in progress and
|
|
220
|
+
`turn.start` has not been sent; await it before sending any other turn command.
|
|
221
|
+
After a planned rotation, an old epoch with outstanding `usage.committed`
|
|
222
|
+
events drains in parallel for up to five seconds and closes as soon as all
|
|
223
|
+
known completed turns settle. This event is best-effort; use history and usage
|
|
224
|
+
APIs as the durable source of truth.
|
|
225
|
+
|
|
226
|
+
The managed connection never buffers turn content or replays a command. The
|
|
227
|
+
bounded `startTurnWhenReady(...)` wait happens before its first WebSocket
|
|
228
|
+
write. If a WebSocket is interrupted while a turn is active, its iterator rejects with
|
|
229
|
+
`BreezeBlueRealtimeError` and `error.code === "TURN_INTERRUPTED"`; decide from
|
|
230
|
+
your application conversation state whether and how to start a new turn.
|
|
231
|
+
Treat the manager as an active realtime call, not a presence channel. Always
|
|
232
|
+
call `connection.close()` when the call ends, the user leaves, or the page
|
|
233
|
+
enters a long-lived background state; otherwise its heartbeat intentionally
|
|
234
|
+
keeps a server WebSocket slot occupied.
|
|
235
|
+
|
|
165
236
|
To cut time to first audio, create the session ahead of time (for example while
|
|
166
237
|
your app is still preparing the turn) and connect with its `clientSecret` when
|
|
167
238
|
the first text is ready — only the WebSocket handshake remains:
|
|
168
239
|
|
|
169
240
|
```ts
|
|
170
241
|
const session = await client.textToSpeech.realtime.createSession("voc_...", {
|
|
171
|
-
modelId: "
|
|
242
|
+
modelId: "breeze-tts-2",
|
|
172
243
|
});
|
|
173
244
|
|
|
174
245
|
// Later, when the first text is ready:
|
|
@@ -189,16 +260,57 @@ const connection = await browserClient.textToSpeech.realtime.connect("voc_...",
|
|
|
189
260
|
});
|
|
190
261
|
```
|
|
191
262
|
|
|
263
|
+
For a managed browser connection, provide a `sessionFactory`. The SDK invokes it
|
|
264
|
+
for every physical epoch, so the callback must fetch a newly minted secret from
|
|
265
|
+
your backend rather than cache the first response. Session configuration belongs
|
|
266
|
+
in that backend request when a custom factory is used:
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
import { BreezeBlueRealtimeError } from "@breeze.blue/sdk";
|
|
270
|
+
|
|
271
|
+
const connection = await browserClient.textToSpeech.realtime.connectManaged("voc_...", {
|
|
272
|
+
sessionFactory: async ({ signal }) => {
|
|
273
|
+
const response = await fetch("/api/breeze-realtime-session", {
|
|
274
|
+
method: "POST",
|
|
275
|
+
signal,
|
|
276
|
+
});
|
|
277
|
+
if (!response.ok) {
|
|
278
|
+
const reconnect =
|
|
279
|
+
[408, 425, 429].includes(response.status) || response.status >= 500;
|
|
280
|
+
throw new BreezeBlueRealtimeError("Could not create realtime session", {
|
|
281
|
+
code: "SESSION_FACTORY_ERROR",
|
|
282
|
+
reconnect,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
return response.json(); // { clientSecret, websocketUrl? }
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Honor the factory `signal`: the SDK aborts it when the logical connection closes
|
|
291
|
+
or the physical-epoch timeout expires. A custom callback that ignores the
|
|
292
|
+
signal must still enforce its own bounded request timeout.
|
|
293
|
+
|
|
192
294
|
Session parameters (`modelId`, `languageCode`, `instructions`, `voiceSettings`,
|
|
193
295
|
`inactivityTimeoutSeconds`, `enableLogging`) are fixed when the session is
|
|
194
296
|
created. `connect` ignores them when `clientSecret` or `websocketUrl` is
|
|
195
297
|
provided and logs a warning.
|
|
196
298
|
|
|
197
299
|
If a realtime WebSocket is interrupted by a network change, service deployment,
|
|
198
|
-
or upstream realtime worker restart,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
300
|
+
or upstream realtime worker restart, `connectManaged(...)` handles bounded
|
|
301
|
+
reconnects only while there is no active turn. With the lower-level
|
|
302
|
+
`connect(...)`, handle `error.meta.reconnect === true` or a `session.closed`
|
|
303
|
+
event with `reconnect === true` by creating a new session and starting a new
|
|
304
|
+
turn from your own conversation state. Active turns are never resumed in place.
|
|
305
|
+
During a managed reconnect, transient session-creation responses (408, 425, 429,
|
|
306
|
+
and 5xx) share the same bounded reconnect budget; other 4xx responses fail the
|
|
307
|
+
logical connection immediately. A custom `sessionFactory` should preserve that
|
|
308
|
+
distinction with `new BreezeBlueRealtimeError(message, { reconnect })`; a plain
|
|
309
|
+
`Error` cannot communicate a terminal policy response and is treated as
|
|
310
|
+
transient inside the same bounded budget. `GENERATION_CAPACITY_EXCEEDED` is
|
|
311
|
+
turn-scoped: wait for the following `turn.cancelled`, back off using
|
|
312
|
+
`meta.retryAfterSeconds`, and start a new turn on the same managed logical
|
|
313
|
+
connection without replaying text.
|
|
202
314
|
|
|
203
315
|
The API uses the default text-to-speech model when `modelId` is omitted. If
|
|
204
316
|
you need to select a model explicitly, call `client.models.list()` and pass one
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AudioResponse } from "./audio.js";
|
|
2
|
-
import type { AudioRequestOptions, BreezeBlueWebSocket, AsyncTextToSpeechJob, Balance, BreezeBlueClientOptions, GenericStatus, GenerationJob, HistoryItem, HistoryList, HistoryListParams, Model, RequestOptions, RealtimeTextToSpeechConnectOptions, RealtimeTextToSpeechEvent, RealtimeTextToSpeechMessage, RealtimeTextToSpeechSession, RealtimeTextToSpeechSessionRequest, SavedVoice, SaveVoiceRequest, StreamTextToSpeechOptions, TextToSpeechRequest, TtsEnhanceRequest, TtsEnhanceResponse, Usage, UsageParams, Voice, VoiceClonePreview, VoiceClonePreviewRequest, VoiceDesignRequest, VoiceDesignResponse, VoiceEditRequest, VoiceList, VoiceSearchParams, VoiceSettings } from "./types.js";
|
|
2
|
+
import type { AudioRequestOptions, BreezeBlueWebSocket, AsyncTextToSpeechJob, Balance, BreezeBlueClientOptions, GenericStatus, GenerationJob, HistoryItem, HistoryList, HistoryListParams, Model, RequestOptions, RealtimeTextToSpeechConnectOptions, RealtimeTextToSpeechEvent, RealtimeTextToSpeechManagedConnectOptions, RealtimeTextToSpeechMessage, RealtimeTextToSpeechSession, RealtimeTextToSpeechSessionRequest, SavedVoice, SaveVoiceRequest, StreamTextToSpeechOptions, TextToSpeechRequest, TtsEnhanceRequest, TtsEnhanceResponse, Usage, UsageParams, Voice, VoiceClonePreview, VoiceClonePreviewRequest, VoiceDesignRequest, VoiceDesignResponse, VoiceEditRequest, VoiceList, VoiceSearchParams, VoiceSettings } from "./types.js";
|
|
3
3
|
export declare class BreezeBlueClient {
|
|
4
4
|
readonly apiKey: string | undefined;
|
|
5
5
|
readonly baseUrl: string;
|
|
@@ -33,6 +33,13 @@ declare class RealtimeTextToSpeechResource {
|
|
|
33
33
|
constructor(client: BreezeBlueClient);
|
|
34
34
|
createSession(voiceId: string, request?: RealtimeTextToSpeechSessionRequest, options?: RequestOptions): Promise<RealtimeTextToSpeechSession>;
|
|
35
35
|
connect(voiceId: string, options?: RealtimeTextToSpeechConnectOptions): Promise<RealtimeTextToSpeechConnection>;
|
|
36
|
+
/**
|
|
37
|
+
* Open an SDK-managed logical connection backed by bounded physical
|
|
38
|
+
* WebSocket sessions. The manager keeps idle sessions alive, rotates at
|
|
39
|
+
* turn boundaries, and performs bounded idle reconnects with fresh
|
|
40
|
+
* credentials. It never replays an interrupted active turn.
|
|
41
|
+
*/
|
|
42
|
+
connectManaged(voiceId: string, options?: RealtimeTextToSpeechManagedConnectOptions): Promise<ManagedRealtimeTextToSpeechConnection>;
|
|
36
43
|
}
|
|
37
44
|
export declare class RealtimeTextToSpeechConnection implements AsyncIterable<RealtimeTextToSpeechMessage> {
|
|
38
45
|
private readonly socket;
|
|
@@ -41,9 +48,11 @@ export declare class RealtimeTextToSpeechConnection implements AsyncIterable<Rea
|
|
|
41
48
|
private closed;
|
|
42
49
|
private queuedBytes;
|
|
43
50
|
private failure;
|
|
51
|
+
private closeEventGraceTimer;
|
|
44
52
|
private constructor();
|
|
45
53
|
static open(socket: BreezeBlueWebSocket, options?: {
|
|
46
54
|
timeout?: number;
|
|
55
|
+
signal?: AbortSignal;
|
|
47
56
|
}): Promise<RealtimeTextToSpeechConnection>;
|
|
48
57
|
startTurn(turnId?: string): void;
|
|
49
58
|
appendText(text: string): void;
|
|
@@ -59,9 +68,101 @@ export declare class RealtimeTextToSpeechConnection implements AsyncIterable<Rea
|
|
|
59
68
|
private sendJson;
|
|
60
69
|
private handleMessage;
|
|
61
70
|
private handleClose;
|
|
71
|
+
private handleSocketError;
|
|
72
|
+
private push;
|
|
73
|
+
private fail;
|
|
74
|
+
private finish;
|
|
75
|
+
private clearCloseEventGraceTimer;
|
|
76
|
+
}
|
|
77
|
+
type RealtimeConnectionFactory = (signal: AbortSignal) => Promise<RealtimeTextToSpeechConnection>;
|
|
78
|
+
/**
|
|
79
|
+
* A logical realtime TTS connection backed by bounded physical WebSocket
|
|
80
|
+
* epochs. Use `textToSpeech.realtime.connectManaged(...)` to create one.
|
|
81
|
+
*
|
|
82
|
+
* The manager automatically keeps an idle session alive, rotates before the
|
|
83
|
+
* server session limit at turn boundaries, and makes bounded reconnect
|
|
84
|
+
* attempts while idle. It does not buffer turn content or replay commands;
|
|
85
|
+
* startTurnWhenReady() may wait before its first turn.start write. If the
|
|
86
|
+
* transport is interrupted during a turn, iteration rejects with
|
|
87
|
+
* `BreezeBlueRealtimeError`.
|
|
88
|
+
*/
|
|
89
|
+
export declare class ManagedRealtimeTextToSpeechConnection implements AsyncIterable<RealtimeTextToSpeechMessage> {
|
|
90
|
+
private readonly createConnection;
|
|
91
|
+
private readonly queue;
|
|
92
|
+
private readonly drainingEpochs;
|
|
93
|
+
private readonly openAttempts;
|
|
94
|
+
private readonly waiters;
|
|
95
|
+
private readonly heartbeatIntervalMs;
|
|
96
|
+
private readonly heartbeatTimeoutMs;
|
|
97
|
+
private readonly readyTimeoutMs;
|
|
98
|
+
private readonly rotationMarginMs;
|
|
99
|
+
private readonly maxPhysicalSessionMs;
|
|
100
|
+
private readonly maxReconnectAttempts;
|
|
101
|
+
private readonly reconnectBaseDelayMs;
|
|
102
|
+
private current;
|
|
103
|
+
private heartbeatTimer;
|
|
104
|
+
private heartbeatAckTimer;
|
|
105
|
+
private rotationTimer;
|
|
106
|
+
private retryDelay;
|
|
107
|
+
private transitionPromise;
|
|
108
|
+
private transitionKind;
|
|
109
|
+
private epochSequence;
|
|
110
|
+
private queuedBytes;
|
|
111
|
+
private activeTurn;
|
|
112
|
+
private rotationPending;
|
|
113
|
+
private closed;
|
|
114
|
+
private failure;
|
|
115
|
+
private constructor();
|
|
116
|
+
static open(createConnection: RealtimeConnectionFactory, options?: RealtimeTextToSpeechManagedConnectOptions): Promise<ManagedRealtimeTextToSpeechConnection>;
|
|
117
|
+
startTurn(turnId?: string): void;
|
|
118
|
+
/**
|
|
119
|
+
* Start a turn on the current physical epoch, waiting only when an idle
|
|
120
|
+
* unexpected reconnect is already replacing a missing epoch.
|
|
121
|
+
*
|
|
122
|
+
* No other turn command is buffered. Await this method before calling
|
|
123
|
+
* appendText(), flush(), endTurn(), or cancelTurn().
|
|
124
|
+
*/
|
|
125
|
+
startTurnWhenReady(turnId?: string, options?: {
|
|
126
|
+
signal?: AbortSignal;
|
|
127
|
+
}): Promise<void>;
|
|
128
|
+
appendText(text: string): void;
|
|
129
|
+
flush(): void;
|
|
130
|
+
endTurn(): void;
|
|
131
|
+
cancelTurn(): void;
|
|
132
|
+
/** Send an immediate ping in addition to the managed keepalive schedule. */
|
|
133
|
+
ping(): void;
|
|
134
|
+
close(): void;
|
|
135
|
+
events(): AsyncIterable<RealtimeTextToSpeechEvent>;
|
|
136
|
+
audio(): AsyncIterable<Uint8Array>;
|
|
137
|
+
[Symbol.asyncIterator](): AsyncIterator<RealtimeTextToSpeechMessage>;
|
|
138
|
+
private openEpoch;
|
|
139
|
+
private installEpoch;
|
|
140
|
+
private pumpEpoch;
|
|
141
|
+
private handleEpochMessage;
|
|
142
|
+
private handleEpochEnd;
|
|
143
|
+
private requestUnexpectedReconnect;
|
|
144
|
+
private beginTransition;
|
|
145
|
+
private replaceEpoch;
|
|
146
|
+
private deferPlannedTransitionForActiveTurn;
|
|
147
|
+
private scheduleTimers;
|
|
148
|
+
private scheduleNextHeartbeat;
|
|
149
|
+
private acknowledgeHeartbeat;
|
|
150
|
+
private requireCurrentConnection;
|
|
151
|
+
private waitForStartTurnTransition;
|
|
152
|
+
private throwIfStartTurnAborted;
|
|
62
153
|
private push;
|
|
63
154
|
private fail;
|
|
64
155
|
private finish;
|
|
156
|
+
private clearTimers;
|
|
157
|
+
private waitForRetryDelay;
|
|
158
|
+
private cancelRetryDelay;
|
|
159
|
+
private completeOpenAttempt;
|
|
160
|
+
private cancelOpenAttempt;
|
|
161
|
+
private cancelOpenAttempts;
|
|
162
|
+
private beginSettlementDrain;
|
|
163
|
+
private handleSettlementDrainMessage;
|
|
164
|
+
private finishSettlementDrain;
|
|
165
|
+
private closeSettlementDrains;
|
|
65
166
|
}
|
|
66
167
|
declare class GenerationJobsResource {
|
|
67
168
|
private readonly client;
|