@breeze.blue/sdk 0.3.0 → 0.4.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 +19 -0
- package/README.md +14 -0
- package/dist/client.d.ts +3 -1
- package/dist/client.js +20 -6
- package/dist/errors.js +3 -0
- package/dist/types.d.ts +25 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
- Added `client.textToSpeech.aiRewrite(...)` for instruction-only
|
|
6
|
+
text-to-speech AI Rewrite.
|
|
7
|
+
- Added `client.voices.random()` for fetching one visible voice to use as a
|
|
8
|
+
text-to-speech reference voice.
|
|
9
|
+
- Added account usage filters for API key, status class, client type, and date
|
|
10
|
+
range, plus usage log fields for API key attribution, request duration, first
|
|
11
|
+
audio chunk latency, and client telemetry.
|
|
12
|
+
- Improved typed error mapping for generation timeouts and fallback 429 rate
|
|
13
|
+
limit responses.
|
|
14
|
+
|
|
15
|
+
## 0.3.1
|
|
16
|
+
|
|
17
|
+
- Added SDK-side validation for `voices.createClonePreview(...)` and
|
|
18
|
+
`voices.edit(...)` reference audio inputs so `file` and single-item `files`
|
|
19
|
+
forms are accepted, while missing or multiple clone samples are rejected
|
|
20
|
+
before sending a request.
|
|
21
|
+
|
|
3
22
|
## 0.3.0
|
|
4
23
|
|
|
5
24
|
- Added async text-to-speech helpers: `client.textToSpeech.createJob(...)`,
|
package/README.md
CHANGED
|
@@ -73,6 +73,11 @@ const audio = await client.textToSpeech.convert("voc_...", {
|
|
|
73
73
|
const audioStream = await client.textToSpeech.stream("voc_...", {
|
|
74
74
|
text: "Stream this line.",
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
const rewritten = await client.textToSpeech.aiRewrite({
|
|
78
|
+
instruction: "Calm, warm, bedtime narration.",
|
|
79
|
+
languageCode: "en",
|
|
80
|
+
});
|
|
76
81
|
```
|
|
77
82
|
|
|
78
83
|
Use async text-to-speech for long text, reference-heavy voices, or batch
|
|
@@ -135,6 +140,9 @@ const firstVoiceId = voices.voices[0].voiceId;
|
|
|
135
140
|
|
|
136
141
|
const voice = await client.voices.get(firstVoiceId);
|
|
137
142
|
const settings = await client.voices.getSettings(firstVoiceId);
|
|
143
|
+
|
|
144
|
+
const randomVoice = await client.voices.random();
|
|
145
|
+
console.log(randomVoice.voiceId, randomVoice.name);
|
|
138
146
|
```
|
|
139
147
|
|
|
140
148
|
Breeze voice creation is always two steps: produce a **preview**, let the
|
|
@@ -163,6 +171,8 @@ const design = await client.voices.createDesignPreview({
|
|
|
163
171
|
generatedVoiceId = design.previews[0].generatedVoiceId;
|
|
164
172
|
```
|
|
165
173
|
|
|
174
|
+
`files` is also accepted with exactly one item.
|
|
175
|
+
|
|
166
176
|
Stream the preview so the user can audition it, then save the one they
|
|
167
177
|
pick:
|
|
168
178
|
|
|
@@ -190,6 +200,10 @@ await client.voices.delete(saved.voiceId);
|
|
|
190
200
|
const models = await client.models.list();
|
|
191
201
|
const balance = await client.account.balance();
|
|
192
202
|
const usage = await client.account.usage({ days: 7 });
|
|
203
|
+
const keyUsage = await client.account.usage({
|
|
204
|
+
apiKeyId: "key_01hprod",
|
|
205
|
+
clientType: "sdk",
|
|
206
|
+
});
|
|
193
207
|
|
|
194
208
|
const history = await client.history.list({ pageSize: 10 });
|
|
195
209
|
const item = await client.history.get(history.history[0].historyItemId);
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AudioResponse } from "./audio.js";
|
|
2
|
-
import type { AudioRequestOptions, AsyncTextToSpeechJob, Balance, BreezeBlueClientOptions, GenericStatus, GenerationJob, HistoryItem, HistoryList, HistoryListParams, Model, RequestOptions, SaveVoiceRequest, StreamTextToSpeechOptions, TextToSpeechRequest, Usage, UsageParams, Voice, VoiceClonePreview, VoiceClonePreviewRequest, VoiceDesignRequest, VoiceDesignResponse, VoiceEditRequest, VoiceList, VoiceSearchParams, VoiceSettings } from "./types.js";
|
|
2
|
+
import type { AudioRequestOptions, AsyncTextToSpeechJob, Balance, BreezeBlueClientOptions, GenericStatus, GenerationJob, HistoryItem, HistoryList, HistoryListParams, Model, RequestOptions, SaveVoiceRequest, StreamTextToSpeechOptions, TextToSpeechRequest, TtsAiRewriteRequest, TtsAiRewriteResponse, 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;
|
|
5
5
|
readonly baseUrl: string;
|
|
@@ -24,6 +24,7 @@ declare class TextToSpeechResource {
|
|
|
24
24
|
convert(voiceId: string, request: TextToSpeechRequest, options?: AudioRequestOptions): Promise<AudioResponse>;
|
|
25
25
|
createJob(voiceId: string, request: TextToSpeechRequest, options?: AudioRequestOptions): Promise<AsyncTextToSpeechJob>;
|
|
26
26
|
stream(voiceId: string, request: TextToSpeechRequest, options?: StreamTextToSpeechOptions): Promise<AudioResponse>;
|
|
27
|
+
aiRewrite(request: TtsAiRewriteRequest, options?: RequestOptions): Promise<TtsAiRewriteResponse>;
|
|
27
28
|
}
|
|
28
29
|
declare class GenerationJobsResource {
|
|
29
30
|
private readonly client;
|
|
@@ -44,6 +45,7 @@ declare class VoicesResource {
|
|
|
44
45
|
constructor(client: BreezeBlueClient);
|
|
45
46
|
search(params?: VoiceSearchParams, options?: RequestOptions): Promise<VoiceList>;
|
|
46
47
|
get(voiceId: string, options?: RequestOptions): Promise<Voice>;
|
|
48
|
+
random(options?: RequestOptions): Promise<Voice>;
|
|
47
49
|
edit(voiceId: string, request: VoiceEditRequest, options?: RequestOptions): Promise<GenericStatus>;
|
|
48
50
|
delete(voiceId: string, options?: RequestOptions): Promise<GenericStatus>;
|
|
49
51
|
getSettings(voiceId: string, options?: RequestOptions): Promise<Required<VoiceSettings>>;
|
package/dist/client.js
CHANGED
|
@@ -96,6 +96,9 @@ class TextToSpeechResource {
|
|
|
96
96
|
enableLogging: options.enableLogging,
|
|
97
97
|
}, request, options);
|
|
98
98
|
}
|
|
99
|
+
aiRewrite(request, options) {
|
|
100
|
+
return this.client.requestJson("POST", "/v1/text-to-speech/ai-rewrite", undefined, request, options);
|
|
101
|
+
}
|
|
99
102
|
}
|
|
100
103
|
class GenerationJobsResource {
|
|
101
104
|
client;
|
|
@@ -129,6 +132,9 @@ class VoicesResource {
|
|
|
129
132
|
get(voiceId, options) {
|
|
130
133
|
return this.client.requestJson("GET", `/v1/voices/${encodeURIComponent(voiceId)}`, undefined, undefined, options);
|
|
131
134
|
}
|
|
135
|
+
random(options) {
|
|
136
|
+
return this.client.requestJson("GET", "/v1/voices/random", undefined, undefined, options);
|
|
137
|
+
}
|
|
132
138
|
edit(voiceId, request, options) {
|
|
133
139
|
return this.client.requestJson("PATCH", `/v1/voices/${encodeURIComponent(voiceId)}`, undefined, voiceEditForm(request), options);
|
|
134
140
|
}
|
|
@@ -279,7 +285,7 @@ function clonePreviewForm(request) {
|
|
|
279
285
|
appendOptional(form, "labels", request.labels ? JSON.stringify(request.labels) : undefined);
|
|
280
286
|
appendOptional(form, "text", request.text);
|
|
281
287
|
appendOptional(form, "instructions", request.instructions);
|
|
282
|
-
for (const file of normalizeFiles(request.file, request.files)) {
|
|
288
|
+
for (const file of normalizeFiles(request.file, request.files, { required: true })) {
|
|
283
289
|
appendFile(form, "files", file);
|
|
284
290
|
}
|
|
285
291
|
return form;
|
|
@@ -289,7 +295,7 @@ function voiceEditForm(request) {
|
|
|
289
295
|
form.set("name", request.name);
|
|
290
296
|
appendOptional(form, "description", request.description);
|
|
291
297
|
appendOptional(form, "labels", request.labels ? JSON.stringify(request.labels) : undefined);
|
|
292
|
-
for (const file of normalizeFiles(request.file, request.files)) {
|
|
298
|
+
for (const file of normalizeFiles(request.file, request.files, { required: false })) {
|
|
293
299
|
appendFile(form, "files", file);
|
|
294
300
|
}
|
|
295
301
|
return form;
|
|
@@ -299,10 +305,18 @@ function appendOptional(form, key, value) {
|
|
|
299
305
|
return;
|
|
300
306
|
form.set(key, String(value));
|
|
301
307
|
}
|
|
302
|
-
function normalizeFiles(file, files) {
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
|
|
308
|
+
function normalizeFiles(file, files, options) {
|
|
309
|
+
if (file !== undefined && files !== undefined) {
|
|
310
|
+
throw new BreezeBlueConfigurationError("Pass either file or files, not both.");
|
|
311
|
+
}
|
|
312
|
+
const selected = files !== undefined ? files : file === undefined ? [] : [file];
|
|
313
|
+
if (options.required && selected.length === 0) {
|
|
314
|
+
throw new BreezeBlueConfigurationError("Exactly one sample file is required.");
|
|
315
|
+
}
|
|
316
|
+
if (selected.length > 1) {
|
|
317
|
+
throw new BreezeBlueConfigurationError("Exactly one sample file is currently supported.");
|
|
318
|
+
}
|
|
319
|
+
return selected;
|
|
306
320
|
}
|
|
307
321
|
function appendFile(form, key, input) {
|
|
308
322
|
const upload = isUploadFile(input) ? input : { data: input };
|
package/dist/errors.js
CHANGED
|
@@ -68,6 +68,7 @@ const codeErrorMap = new Map([
|
|
|
68
68
|
["UPSTREAM_BILLING_ERROR", BreezeBlueUpstreamError],
|
|
69
69
|
["UPSTREAM_GENERATION_ERROR", BreezeBlueUpstreamError],
|
|
70
70
|
["UPSTREAM_TIMEOUT", BreezeBlueUpstreamError],
|
|
71
|
+
["GENERATION_TIMEOUT", BreezeBlueUpstreamError],
|
|
71
72
|
["UPSTREAM_GENERATION_SERVICE_ERROR", BreezeBlueUpstreamError],
|
|
72
73
|
["UPSTREAM_ASSET_STORAGE_ERROR", BreezeBlueUpstreamError],
|
|
73
74
|
["GENERATION_INVALID_RESPONSE", BreezeBlueUpstreamError],
|
|
@@ -141,6 +142,8 @@ function fallbackCode(status) {
|
|
|
141
142
|
return "VALIDATION_ERROR";
|
|
142
143
|
if (status === 425)
|
|
143
144
|
return "GENERATION_NOT_READY";
|
|
145
|
+
if (status === 429)
|
|
146
|
+
return "RATE_LIMITED";
|
|
144
147
|
if (status === 502)
|
|
145
148
|
return "UPSTREAM_GENERATION_ERROR";
|
|
146
149
|
if (status === 503)
|
package/dist/types.d.ts
CHANGED
|
@@ -46,6 +46,14 @@ export interface TextToSpeechRequest {
|
|
|
46
46
|
applyTextNormalization?: string;
|
|
47
47
|
applyLanguageTextNormalization?: boolean;
|
|
48
48
|
}
|
|
49
|
+
export interface TtsAiRewriteRequest {
|
|
50
|
+
instruction: string;
|
|
51
|
+
languageCode?: string | null;
|
|
52
|
+
}
|
|
53
|
+
export interface TtsAiRewriteResponse {
|
|
54
|
+
instruction: string;
|
|
55
|
+
languageCode: string;
|
|
56
|
+
}
|
|
49
57
|
export interface AsyncTextToSpeechJob {
|
|
50
58
|
generationJobId: string;
|
|
51
59
|
historyItemId: string;
|
|
@@ -192,6 +200,9 @@ export interface HistoryItem {
|
|
|
192
200
|
requestId?: string | null;
|
|
193
201
|
latencyMs?: number | null;
|
|
194
202
|
httpStatus?: number | null;
|
|
203
|
+
billableUnits?: number | null;
|
|
204
|
+
cost?: number | null;
|
|
205
|
+
costMillicredits?: number | null;
|
|
195
206
|
[key: string]: unknown;
|
|
196
207
|
}
|
|
197
208
|
export interface HistoryList {
|
|
@@ -244,15 +255,24 @@ export interface UsageItem {
|
|
|
244
255
|
endpoint: string;
|
|
245
256
|
method: string;
|
|
246
257
|
status: number;
|
|
258
|
+
apiKeyId?: string | null;
|
|
259
|
+
apiKeyName?: string | null;
|
|
260
|
+
apiKeyPrefix?: string | null;
|
|
247
261
|
model?: string | null;
|
|
248
262
|
billableUnits?: number | null;
|
|
249
263
|
cost?: number | null;
|
|
250
264
|
costMillicredits?: number | null;
|
|
251
265
|
latencyMs?: number | null;
|
|
266
|
+
durationMs?: number | null;
|
|
267
|
+
firstAudioChunkMs?: number | null;
|
|
268
|
+
requestDurationMs?: number | null;
|
|
252
269
|
traceId?: string | null;
|
|
253
270
|
requestId?: string | null;
|
|
254
271
|
textCharacters?: number | null;
|
|
255
272
|
actionCode?: string | null;
|
|
273
|
+
clientType?: string | null;
|
|
274
|
+
clientName?: string | null;
|
|
275
|
+
clientVersion?: string | null;
|
|
256
276
|
createdAt?: string | null;
|
|
257
277
|
[key: string]: unknown;
|
|
258
278
|
}
|
|
@@ -270,6 +290,11 @@ export interface UsageParams {
|
|
|
270
290
|
days?: number;
|
|
271
291
|
search?: string;
|
|
272
292
|
method?: string;
|
|
293
|
+
apiKeyId?: string;
|
|
294
|
+
statusClass?: "2xx" | "4xx" | "5xx" | "other" | string;
|
|
295
|
+
clientType?: "api" | "sdk" | "cli" | string;
|
|
296
|
+
from?: string;
|
|
297
|
+
to?: string;
|
|
273
298
|
page?: number;
|
|
274
299
|
pageSize?: number;
|
|
275
300
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.4.0";
|
|
2
2
|
export declare const SDK_NAME = "@breeze.blue/sdk";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.
|
|
1
|
+
export const SDK_VERSION = "0.4.0";
|
|
2
2
|
export const SDK_NAME = "@breeze.blue/sdk";
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@breeze.blue/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "ESM-first TypeScript SDK for the Breeze Blue Developer API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Breeze Blue <support@breeze.blue>",
|
|
7
|
-
"homepage": "https://
|
|
7
|
+
"homepage": "https://breezeblue.ai",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"audio",
|
|
10
10
|
"breeze",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"typescript": "^5.9.3"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "
|
|
49
|
-
"typecheck": "
|
|
48
|
+
"build": "node node_modules/typescript/bin/tsc -p tsconfig.json",
|
|
49
|
+
"typecheck": "node node_modules/typescript/bin/tsc -p tsconfig.json --noEmit",
|
|
50
50
|
"test": "pnpm run build && node --test ./test/*.test.js"
|
|
51
51
|
}
|
|
52
52
|
}
|