kugelaudio 0.6.0 → 0.6.1
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 +6 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -5
- package/dist/index.mjs +8 -5
- package/package.json +1 -1
- package/src/client.test.ts +24 -0
- package/src/client.ts +2 -2
- package/src/errors.ts +16 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [kugelaudio-v0.6.1](https://github.com/Kugelaudio/KugelAudio/compare/js-sdk-v0.6.0...js-sdk-v0.6.1) (2026-06-04)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **python-sdk:** propagate ingress errors through SDK integrations ([#1313](https://github.com/Kugelaudio/KugelAudio/issues/1313)) ([3ae2e03](https://github.com/Kugelaudio/KugelAudio/commit/3ae2e03745b49cca0712c20d9a658c160f4b6f38))
|
|
6
|
+
|
|
1
7
|
## [kugelaudio-v0.6.0](https://github.com/Kugelaudio/KugelAudio/compare/js-sdk-v0.5.0...js-sdk-v0.6.0) (2026-06-01)
|
|
2
8
|
|
|
3
9
|
### Features
|
package/dist/index.d.mts
CHANGED
|
@@ -1224,6 +1224,8 @@ declare const ErrorCodes: {
|
|
|
1224
1224
|
readonly VALIDATION: "VALIDATION_ERROR";
|
|
1225
1225
|
readonly INTERNAL: "INTERNAL_ERROR";
|
|
1226
1226
|
readonly NOT_FOUND: "NOT_FOUND";
|
|
1227
|
+
readonly MISSING_VOICE_ID: "MISSING_VOICE_ID";
|
|
1228
|
+
readonly TOO_MANY_CONTEXTS: "TOO_MANY_CONTEXTS";
|
|
1227
1229
|
};
|
|
1228
1230
|
type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];
|
|
1229
1231
|
declare const WsCloseCodes: {
|
|
@@ -1305,11 +1307,12 @@ interface HttpResponseLike {
|
|
|
1305
1307
|
declare function classifyHttpError(status: number, bodyText: string, headers: HttpResponseLike['headers']): KugelAudioError;
|
|
1306
1308
|
/**
|
|
1307
1309
|
* Build a `KugelAudioError` from a server-sent WebSocket error frame
|
|
1308
|
-
* (`{error, error_code,
|
|
1310
|
+
* (`{error, error_code, code}`).
|
|
1309
1311
|
*/
|
|
1310
1312
|
declare function classifyWsFrame(data: {
|
|
1311
1313
|
error?: string;
|
|
1312
1314
|
error_code?: string;
|
|
1315
|
+
code?: number;
|
|
1313
1316
|
retry_after?: number;
|
|
1314
1317
|
}): KugelAudioError;
|
|
1315
1318
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1224,6 +1224,8 @@ declare const ErrorCodes: {
|
|
|
1224
1224
|
readonly VALIDATION: "VALIDATION_ERROR";
|
|
1225
1225
|
readonly INTERNAL: "INTERNAL_ERROR";
|
|
1226
1226
|
readonly NOT_FOUND: "NOT_FOUND";
|
|
1227
|
+
readonly MISSING_VOICE_ID: "MISSING_VOICE_ID";
|
|
1228
|
+
readonly TOO_MANY_CONTEXTS: "TOO_MANY_CONTEXTS";
|
|
1227
1229
|
};
|
|
1228
1230
|
type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];
|
|
1229
1231
|
declare const WsCloseCodes: {
|
|
@@ -1305,11 +1307,12 @@ interface HttpResponseLike {
|
|
|
1305
1307
|
declare function classifyHttpError(status: number, bodyText: string, headers: HttpResponseLike['headers']): KugelAudioError;
|
|
1306
1308
|
/**
|
|
1307
1309
|
* Build a `KugelAudioError` from a server-sent WebSocket error frame
|
|
1308
|
-
* (`{error, error_code,
|
|
1310
|
+
* (`{error, error_code, code}`).
|
|
1309
1311
|
*/
|
|
1310
1312
|
declare function classifyWsFrame(data: {
|
|
1311
1313
|
error?: string;
|
|
1312
1314
|
error_code?: string;
|
|
1315
|
+
code?: number;
|
|
1313
1316
|
retry_after?: number;
|
|
1314
1317
|
}): KugelAudioError;
|
|
1315
1318
|
/**
|
package/dist/index.js
CHANGED
|
@@ -233,7 +233,9 @@ var ErrorCodes = {
|
|
|
233
233
|
EMPTY_AUDIO: "EMPTY_AUDIO",
|
|
234
234
|
VALIDATION: "VALIDATION_ERROR",
|
|
235
235
|
INTERNAL: "INTERNAL_ERROR",
|
|
236
|
-
NOT_FOUND: "NOT_FOUND"
|
|
236
|
+
NOT_FOUND: "NOT_FOUND",
|
|
237
|
+
MISSING_VOICE_ID: "MISSING_VOICE_ID",
|
|
238
|
+
TOO_MANY_CONTEXTS: "TOO_MANY_CONTEXTS"
|
|
237
239
|
};
|
|
238
240
|
var WsCloseCodes = {
|
|
239
241
|
UNAUTHORIZED: 4001,
|
|
@@ -317,10 +319,10 @@ function build(status, errorCode, message, opts = {}) {
|
|
|
317
319
|
if (errorCode === ErrorCodes.INSUFFICIENT_CREDITS || status === 402) {
|
|
318
320
|
return new InsufficientCreditsError(message || void 0, common);
|
|
319
321
|
}
|
|
320
|
-
if (errorCode === ErrorCodes.RATE_LIMITED || status === 429) {
|
|
322
|
+
if (errorCode === ErrorCodes.RATE_LIMITED || errorCode === ErrorCodes.TOO_MANY_CONTEXTS || status === 429) {
|
|
321
323
|
return new RateLimitError(message || void 0, common);
|
|
322
324
|
}
|
|
323
|
-
if (errorCode === ErrorCodes.VALIDATION || status === 400) {
|
|
325
|
+
if (errorCode === ErrorCodes.VALIDATION || errorCode === ErrorCodes.MISSING_VOICE_ID || status === 400) {
|
|
324
326
|
return new ValidationError(message || "Request validation failed.", common);
|
|
325
327
|
}
|
|
326
328
|
if (errorCode === ErrorCodes.MODEL_UNAVAILABLE || status === 503) {
|
|
@@ -380,8 +382,9 @@ function classifyHttpError(status, bodyText, headers) {
|
|
|
380
382
|
function classifyWsFrame(data) {
|
|
381
383
|
const errorCode = data.error_code;
|
|
382
384
|
const message = data.error ?? "Server reported an error.";
|
|
385
|
+
const status = typeof data.code === "number" ? data.code : void 0;
|
|
383
386
|
const retryAfter = typeof data.retry_after === "number" ? data.retry_after : void 0;
|
|
384
|
-
return build(
|
|
387
|
+
return build(status, errorCode, message, { retryAfter });
|
|
385
388
|
}
|
|
386
389
|
function classifyWsClose(code, reason) {
|
|
387
390
|
const reasonTxt = (reason ?? "").trim();
|
|
@@ -1303,7 +1306,7 @@ var MultiContextSession = class {
|
|
|
1303
1306
|
const data = JSON.parse(messageData);
|
|
1304
1307
|
if (data.error) {
|
|
1305
1308
|
this.callbacks.onError?.(
|
|
1306
|
-
|
|
1309
|
+
classifyWsFrame(data),
|
|
1307
1310
|
data.context_id
|
|
1308
1311
|
);
|
|
1309
1312
|
return;
|
package/dist/index.mjs
CHANGED
|
@@ -195,7 +195,9 @@ var ErrorCodes = {
|
|
|
195
195
|
EMPTY_AUDIO: "EMPTY_AUDIO",
|
|
196
196
|
VALIDATION: "VALIDATION_ERROR",
|
|
197
197
|
INTERNAL: "INTERNAL_ERROR",
|
|
198
|
-
NOT_FOUND: "NOT_FOUND"
|
|
198
|
+
NOT_FOUND: "NOT_FOUND",
|
|
199
|
+
MISSING_VOICE_ID: "MISSING_VOICE_ID",
|
|
200
|
+
TOO_MANY_CONTEXTS: "TOO_MANY_CONTEXTS"
|
|
199
201
|
};
|
|
200
202
|
var WsCloseCodes = {
|
|
201
203
|
UNAUTHORIZED: 4001,
|
|
@@ -279,10 +281,10 @@ function build(status, errorCode, message, opts = {}) {
|
|
|
279
281
|
if (errorCode === ErrorCodes.INSUFFICIENT_CREDITS || status === 402) {
|
|
280
282
|
return new InsufficientCreditsError(message || void 0, common);
|
|
281
283
|
}
|
|
282
|
-
if (errorCode === ErrorCodes.RATE_LIMITED || status === 429) {
|
|
284
|
+
if (errorCode === ErrorCodes.RATE_LIMITED || errorCode === ErrorCodes.TOO_MANY_CONTEXTS || status === 429) {
|
|
283
285
|
return new RateLimitError(message || void 0, common);
|
|
284
286
|
}
|
|
285
|
-
if (errorCode === ErrorCodes.VALIDATION || status === 400) {
|
|
287
|
+
if (errorCode === ErrorCodes.VALIDATION || errorCode === ErrorCodes.MISSING_VOICE_ID || status === 400) {
|
|
286
288
|
return new ValidationError(message || "Request validation failed.", common);
|
|
287
289
|
}
|
|
288
290
|
if (errorCode === ErrorCodes.MODEL_UNAVAILABLE || status === 503) {
|
|
@@ -342,8 +344,9 @@ function classifyHttpError(status, bodyText, headers) {
|
|
|
342
344
|
function classifyWsFrame(data) {
|
|
343
345
|
const errorCode = data.error_code;
|
|
344
346
|
const message = data.error ?? "Server reported an error.";
|
|
347
|
+
const status = typeof data.code === "number" ? data.code : void 0;
|
|
345
348
|
const retryAfter = typeof data.retry_after === "number" ? data.retry_after : void 0;
|
|
346
|
-
return build(
|
|
349
|
+
return build(status, errorCode, message, { retryAfter });
|
|
347
350
|
}
|
|
348
351
|
function classifyWsClose(code, reason) {
|
|
349
352
|
const reasonTxt = (reason ?? "").trim();
|
|
@@ -1265,7 +1268,7 @@ var MultiContextSession = class {
|
|
|
1265
1268
|
const data = JSON.parse(messageData);
|
|
1266
1269
|
if (data.error) {
|
|
1267
1270
|
this.callbacks.onError?.(
|
|
1268
|
-
|
|
1271
|
+
classifyWsFrame(data),
|
|
1269
1272
|
data.context_id
|
|
1270
1273
|
);
|
|
1271
1274
|
return;
|
package/package.json
CHANGED
package/src/client.test.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
10
10
|
import { KugelAudio } from './client';
|
|
11
|
+
import { RateLimitError } from './errors';
|
|
11
12
|
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Minimal WebSocket mock
|
|
@@ -660,4 +661,27 @@ describe('MultiContextSession closeContext', () => {
|
|
|
660
661
|
expect(sent.close_context).toBe(true);
|
|
661
662
|
expect(sent.immediate).toBeUndefined();
|
|
662
663
|
});
|
|
664
|
+
|
|
665
|
+
it('maps ingress context-cap errors to typed callback errors', async () => {
|
|
666
|
+
const errors: Array<{ contextId?: string; error: Error }> = [];
|
|
667
|
+
const session = client.tts.createMultiContextSession({ defaultVoiceId: 1 });
|
|
668
|
+
await session.connect({
|
|
669
|
+
onError: (error, contextId) => errors.push({ contextId, error }),
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
mockWs.onmessage?.({
|
|
673
|
+
data: JSON.stringify({
|
|
674
|
+
error: 'Too many concurrent contexts',
|
|
675
|
+
error_code: 'TOO_MANY_CONTEXTS',
|
|
676
|
+
code: 429,
|
|
677
|
+
context_id: 'ctx1',
|
|
678
|
+
}),
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
expect(errors).toHaveLength(1);
|
|
682
|
+
expect(errors[0].contextId).toBe('ctx1');
|
|
683
|
+
expect(errors[0].error).toBeInstanceOf(RateLimitError);
|
|
684
|
+
expect((errors[0].error as RateLimitError).statusCode).toBe(429);
|
|
685
|
+
expect((errors[0].error as RateLimitError).errorCode).toBe('TOO_MANY_CONTEXTS');
|
|
686
|
+
});
|
|
663
687
|
});
|
package/src/client.ts
CHANGED
|
@@ -873,7 +873,7 @@ class TTSResource {
|
|
|
873
873
|
}
|
|
874
874
|
}
|
|
875
875
|
|
|
876
|
-
private parseError(data: { error?: string; error_code?: string; retry_after?: number }): Error {
|
|
876
|
+
private parseError(data: { error?: string; error_code?: string; code?: number; retry_after?: number }): Error {
|
|
877
877
|
return classifyWsFrame(data);
|
|
878
878
|
}
|
|
879
879
|
|
|
@@ -1019,7 +1019,7 @@ class MultiContextSession {
|
|
|
1019
1019
|
|
|
1020
1020
|
if (data.error) {
|
|
1021
1021
|
this.callbacks.onError?.(
|
|
1022
|
-
|
|
1022
|
+
classifyWsFrame(data),
|
|
1023
1023
|
data.context_id
|
|
1024
1024
|
);
|
|
1025
1025
|
return;
|
package/src/errors.ts
CHANGED
|
@@ -17,6 +17,8 @@ export const ErrorCodes = {
|
|
|
17
17
|
VALIDATION: 'VALIDATION_ERROR',
|
|
18
18
|
INTERNAL: 'INTERNAL_ERROR',
|
|
19
19
|
NOT_FOUND: 'NOT_FOUND',
|
|
20
|
+
MISSING_VOICE_ID: 'MISSING_VOICE_ID',
|
|
21
|
+
TOO_MANY_CONTEXTS: 'TOO_MANY_CONTEXTS',
|
|
20
22
|
} as const;
|
|
21
23
|
export type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];
|
|
22
24
|
|
|
@@ -175,10 +177,18 @@ function build(
|
|
|
175
177
|
if (errorCode === ErrorCodes.INSUFFICIENT_CREDITS || status === 402) {
|
|
176
178
|
return new InsufficientCreditsError(message || undefined, common);
|
|
177
179
|
}
|
|
178
|
-
if (
|
|
180
|
+
if (
|
|
181
|
+
errorCode === ErrorCodes.RATE_LIMITED ||
|
|
182
|
+
errorCode === ErrorCodes.TOO_MANY_CONTEXTS ||
|
|
183
|
+
status === 429
|
|
184
|
+
) {
|
|
179
185
|
return new RateLimitError(message || undefined, common);
|
|
180
186
|
}
|
|
181
|
-
if (
|
|
187
|
+
if (
|
|
188
|
+
errorCode === ErrorCodes.VALIDATION ||
|
|
189
|
+
errorCode === ErrorCodes.MISSING_VOICE_ID ||
|
|
190
|
+
status === 400
|
|
191
|
+
) {
|
|
182
192
|
return new ValidationError(message || 'Request validation failed.', common);
|
|
183
193
|
}
|
|
184
194
|
if (errorCode === ErrorCodes.MODEL_UNAVAILABLE || status === 503) {
|
|
@@ -263,17 +273,19 @@ export function classifyHttpError(
|
|
|
263
273
|
|
|
264
274
|
/**
|
|
265
275
|
* Build a `KugelAudioError` from a server-sent WebSocket error frame
|
|
266
|
-
* (`{error, error_code,
|
|
276
|
+
* (`{error, error_code, code}`).
|
|
267
277
|
*/
|
|
268
278
|
export function classifyWsFrame(data: {
|
|
269
279
|
error?: string;
|
|
270
280
|
error_code?: string;
|
|
281
|
+
code?: number;
|
|
271
282
|
retry_after?: number;
|
|
272
283
|
}): KugelAudioError {
|
|
273
284
|
const errorCode = data.error_code;
|
|
274
285
|
const message = data.error ?? 'Server reported an error.';
|
|
286
|
+
const status = typeof data.code === 'number' ? data.code : undefined;
|
|
275
287
|
const retryAfter = typeof data.retry_after === 'number' ? data.retry_after : undefined;
|
|
276
|
-
return build(
|
|
288
|
+
return build(status, errorCode, message, { retryAfter });
|
|
277
289
|
}
|
|
278
290
|
|
|
279
291
|
/**
|