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 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, retry_after}`).
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, retry_after}`).
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(void 0, errorCode, message, { retryAfter });
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
- new KugelAudioError(data.error),
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(void 0, errorCode, message, { retryAfter });
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
- new KugelAudioError(data.error),
1271
+ classifyWsFrame(data),
1269
1272
  data.context_id
1270
1273
  );
1271
1274
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kugelaudio",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Official JavaScript/TypeScript SDK for KugelAudio TTS API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -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
- new KugelAudioError(data.error),
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 (errorCode === ErrorCodes.RATE_LIMITED || status === 429) {
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 (errorCode === ErrorCodes.VALIDATION || status === 400) {
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, retry_after}`).
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(undefined, errorCode, message, { retryAfter });
288
+ return build(status, errorCode, message, { retryAfter });
277
289
  }
278
290
 
279
291
  /**