kugelaudio 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 CHANGED
@@ -1,3 +1,13 @@
1
+ ## [kugelaudio-v0.4.0](https://github.com/Kugelaudio/KugelAudio/compare/js-sdk-v0.3.0...js-sdk-v0.4.0) (2026-05-14)
2
+
3
+ ### Features
4
+
5
+ * **web:** bump kugelaudio SDK to ^0.3.0 to enable per-project dictionary ([#640](https://github.com/Kugelaudio/KugelAudio/issues/640)) ([f503372](https://github.com/Kugelaudio/KugelAudio/commit/f5033728b2febb00cea6b021da5b5309c2c9097f))
6
+
7
+ ### Bug Fixes
8
+
9
+ * **python-sdk,js-sdk,java-sdk:** update regional endpoints ([#660](https://github.com/Kugelaudio/KugelAudio/issues/660)) ([b9a32c0](https://github.com/Kugelaudio/KugelAudio/commit/b9a32c09813c3e9de34a9d0a84ed0e024e1fe158))
10
+
1
11
  # Changelog
2
12
 
3
13
  All notable changes to the KugelAudio JavaScript/TypeScript SDK will be documented in this file.
@@ -5,6 +15,21 @@ All notable changes to the KugelAudio JavaScript/TypeScript SDK will be document
5
15
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
16
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
17
 
18
+ ## [0.3.0](https://github.com/Kugelaudio/KugelAudio/compare/js-sdk-v0.2.3...js-sdk-v0.3.0) (2026-05-10)
19
+
20
+ ### Features
21
+
22
+ * **temperature, projectId, speed** on `tts.stream` / `tts.generate` / multi-context. Required for per-project custom dictionary replacement on the website. ([#273](https://github.com/Kugelaudio/KugelAudio/pull/273))
23
+ * **error classification:** unify across SDKs with actionable messages ([#315](https://github.com/Kugelaudio/KugelAudio/pull/315))
24
+ * **multi-region routing** for all SDKs ([#227](https://github.com/Kugelaudio/KugelAudio/pull/227))
25
+
26
+ ### Bug Fixes
27
+
28
+ * **streaming session close:** per-message-quiet timeout in `StreamingSession.close()` ([#528](https://github.com/Kugelaudio/KugelAudio/pull/528))
29
+ * **multi-context:** remove redundant `is_final` signal from protocol ([#279](https://github.com/Kugelaudio/KugelAudio/pull/279))
30
+ * **websocket:** keep alive across streaming sessions ([#253](https://github.com/Kugelaudio/KugelAudio/pull/253))
31
+ * **release pipeline:** fix stale repo URLs blocking semantic-release ([#637](https://github.com/Kugelaudio/KugelAudio/pull/637))
32
+
8
33
  ## [0.1.3] - 2024-12-25
9
34
 
10
35
  ### Fixed
package/README.md CHANGED
@@ -59,30 +59,28 @@ const client = new KugelAudio({
59
59
 
60
60
  ### Region Selection
61
61
 
62
- KugelAudio is available in multiple regions. The default is EU.
62
+ By default, KugelAudio uses the canonical geo-routed API endpoint. You can
63
+ select the direct EU endpoint when you need to pin traffic to Europe.
63
64
 
64
- | Region | Endpoint |
65
- |--------|----------|
66
- | `eu` | `api.kugelaudio.com` (default) |
67
- | `us` | `us-api.kugelaudio.com` |
68
- | `global` | `global-api.kugelaudio.com` (geo-routed) |
65
+ | Region hint | Endpoint |
66
+ |-------------|----------|
67
+ | default | `api.kugelaudio.com` (geo-routed) |
68
+ | `eu` | `api.eu.kugelaudio.com` |
69
69
 
70
70
  **Option 1 — API key prefix** (simplest, works with env vars):
71
71
 
72
72
  ```typescript
73
- const client = new KugelAudio({ apiKey: 'us-ka_your_api_key' }); // → US
74
- const client = new KugelAudio({ apiKey: 'global-ka_your_api_key' }); // → Global
75
- const client = new KugelAudio({ apiKey: 'eu-ka_your_api_key' }); // → EU (explicit)
76
- const client = new KugelAudio({ apiKey: 'ka_your_api_key' }); // → EU (default)
73
+ const client = new KugelAudio({ apiKey: 'eu-ka_your_api_key' }); // → EU
74
+ const client = new KugelAudio({ apiKey: 'ka_your_api_key' }); // → canonical geo-routed API
77
75
  ```
78
76
 
79
77
  **Option 2 — `region` parameter**:
80
78
 
81
79
  ```typescript
82
- const client = new KugelAudio({ apiKey: 'ka_your_api_key', region: 'us' });
80
+ const client = new KugelAudio({ apiKey: 'ka_your_api_key', region: 'eu' });
83
81
  ```
84
82
 
85
- The prefix is always stripped before authentication. Priority: `apiUrl` > `region` > key prefix > default (EU).
83
+ The prefix is always stripped before authentication. Priority: `apiUrl` > `region` > key prefix > default.
86
84
 
87
85
  ### Single URL Architecture
88
86
 
@@ -361,9 +359,9 @@ try {
361
359
 
362
360
  ```typescript
363
361
  interface KugelAudioOptions {
364
- apiKey: string; // Required (can be prefixed with 'eu-', 'us-', or 'global-')
365
- region?: Region; // 'eu' | 'us' | 'global' (default: 'eu')
366
- apiUrl?: string; // Default: determined by region
362
+ apiKey: string; // Required (can be prefixed with 'eu-' for EU)
363
+ region?: Region; // 'eu' selects the direct EU endpoint
364
+ apiUrl?: string; // Default: https://api.kugelaudio.com
367
365
  ttsUrl?: string; // Default: same as apiUrl
368
366
  timeout?: number; // Default: 60000 (ms)
369
367
  }
@@ -571,4 +569,3 @@ The SDK works in modern browsers with WebSocket support. For Node.js, ensure you
571
569
  ## License
572
570
 
573
571
  MIT
574
-
package/dist/index.d.mts CHANGED
@@ -379,17 +379,17 @@ interface StreamCallbacks {
379
379
  onClose?: () => void;
380
380
  }
381
381
  /**
382
- * Deployment region. Controls which API endpoint the SDK connects to.
383
- * - `'eu'` — `api.kugelaudio.com` (default)
384
- * - `'us'` — `us-api.kugelaudio.com`
385
- * - `'global'` `global-api.kugelaudio.com` (geo-routed)
382
+ * Deployment region. Set `'eu'` to use the direct EU endpoint:
383
+ * `api.eu.kugelaudio.com`.
384
+ *
385
+ * If omitted, the SDK uses `api.kugelaudio.com`.
386
386
  */
387
387
  type Region = 'eu' | 'us' | 'global';
388
388
  /**
389
389
  * KugelAudio client options.
390
390
  */
391
391
  interface KugelAudioOptions {
392
- /** Your KugelAudio API key or JWT token. Can be prefixed with `eu-`, `us-`, or `global-` to select a region (prefix is stripped before auth). */
392
+ /** Your KugelAudio API key or JWT token. Prefix with `eu-` to select the direct EU endpoint (prefix is stripped before auth). */
393
393
  apiKey: string;
394
394
  /** Whether apiKey is a master key (for internal/server-side use). Master keys bypass billing. */
395
395
  isMasterKey?: boolean;
@@ -397,7 +397,7 @@ interface KugelAudioOptions {
397
397
  isToken?: boolean;
398
398
  /** Organisation ID to bill usage against (required for token auth to enable usage recording). */
399
399
  orgId?: number;
400
- /** Deployment region. Takes precedence over API-key prefix but not over `apiUrl`. */
400
+ /** Deployment region. Set `eu` to select the direct EU endpoint. Takes precedence over API-key prefix but not over `apiUrl`. */
401
401
  region?: Region;
402
402
  /** API base URL (default: https://api.kugelaudio.com) */
403
403
  apiUrl?: string;
package/dist/index.d.ts CHANGED
@@ -379,17 +379,17 @@ interface StreamCallbacks {
379
379
  onClose?: () => void;
380
380
  }
381
381
  /**
382
- * Deployment region. Controls which API endpoint the SDK connects to.
383
- * - `'eu'` — `api.kugelaudio.com` (default)
384
- * - `'us'` — `us-api.kugelaudio.com`
385
- * - `'global'` `global-api.kugelaudio.com` (geo-routed)
382
+ * Deployment region. Set `'eu'` to use the direct EU endpoint:
383
+ * `api.eu.kugelaudio.com`.
384
+ *
385
+ * If omitted, the SDK uses `api.kugelaudio.com`.
386
386
  */
387
387
  type Region = 'eu' | 'us' | 'global';
388
388
  /**
389
389
  * KugelAudio client options.
390
390
  */
391
391
  interface KugelAudioOptions {
392
- /** Your KugelAudio API key or JWT token. Can be prefixed with `eu-`, `us-`, or `global-` to select a region (prefix is stripped before auth). */
392
+ /** Your KugelAudio API key or JWT token. Prefix with `eu-` to select the direct EU endpoint (prefix is stripped before auth). */
393
393
  apiKey: string;
394
394
  /** Whether apiKey is a master key (for internal/server-side use). Master keys bypass billing. */
395
395
  isMasterKey?: boolean;
@@ -397,7 +397,7 @@ interface KugelAudioOptions {
397
397
  isToken?: boolean;
398
398
  /** Organisation ID to bill usage against (required for token auth to enable usage recording). */
399
399
  orgId?: number;
400
- /** Deployment region. Takes precedence over API-key prefix but not over `apiUrl`. */
400
+ /** Deployment region. Set `eu` to select the direct EU endpoint. Takes precedence over API-key prefix but not over `apiUrl`. */
401
401
  region?: Region;
402
402
  /** API base URL (default: https://api.kugelaudio.com) */
403
403
  apiUrl?: string;
package/dist/index.js CHANGED
@@ -312,11 +312,9 @@ function getWebSocket() {
312
312
  }
313
313
 
314
314
  // src/client.ts
315
- var REGION_URLS = {
316
- eu: "https://api.kugelaudio.com",
317
- us: "https://us-api.kugelaudio.com",
318
- global: "https://global-api.kugelaudio.com"
319
- };
315
+ var DEFAULT_API_URL = "https://api.kugelaudio.com";
316
+ var EU_API_URL = "https://api.eu.kugelaudio.com";
317
+ var SUPPORTED_REGIONS = ["eu", "us", "global"];
320
318
  var REGION_PREFIXES = ["eu-", "us-", "global-"];
321
319
  function parseApiKey(apiKey) {
322
320
  for (const prefix of REGION_PREFIXES) {
@@ -1539,13 +1537,16 @@ var KugelAudio = class _KugelAudio {
1539
1537
  if (options.apiUrl) {
1540
1538
  this._apiUrl = options.apiUrl.replace(/\/$/, "");
1541
1539
  } else {
1542
- const effectiveRegion = options.region || detectedRegion || "eu";
1543
- if (!(effectiveRegion in REGION_URLS)) {
1540
+ const effectiveRegion = options.region || detectedRegion;
1541
+ if (!effectiveRegion) {
1542
+ this._apiUrl = DEFAULT_API_URL;
1543
+ } else if (!SUPPORTED_REGIONS.includes(effectiveRegion)) {
1544
1544
  throw new ValidationError(
1545
- `Invalid region '${effectiveRegion}'. Must be one of: ${Object.keys(REGION_URLS).join(", ")}.`
1545
+ `Invalid region '${effectiveRegion}'. Must be one of: ${SUPPORTED_REGIONS.join(", ")}.`
1546
1546
  );
1547
+ } else {
1548
+ this._apiUrl = effectiveRegion === "eu" ? EU_API_URL : DEFAULT_API_URL;
1547
1549
  }
1548
- this._apiUrl = REGION_URLS[effectiveRegion];
1549
1550
  }
1550
1551
  this._ttsUrl = (options.ttsUrl || this._apiUrl).replace(/\/$/, "");
1551
1552
  this._timeout = options.timeout || 6e4;
package/dist/index.mjs CHANGED
@@ -277,11 +277,9 @@ function getWebSocket() {
277
277
  }
278
278
 
279
279
  // src/client.ts
280
- var REGION_URLS = {
281
- eu: "https://api.kugelaudio.com",
282
- us: "https://us-api.kugelaudio.com",
283
- global: "https://global-api.kugelaudio.com"
284
- };
280
+ var DEFAULT_API_URL = "https://api.kugelaudio.com";
281
+ var EU_API_URL = "https://api.eu.kugelaudio.com";
282
+ var SUPPORTED_REGIONS = ["eu", "us", "global"];
285
283
  var REGION_PREFIXES = ["eu-", "us-", "global-"];
286
284
  function parseApiKey(apiKey) {
287
285
  for (const prefix of REGION_PREFIXES) {
@@ -1504,13 +1502,16 @@ var KugelAudio = class _KugelAudio {
1504
1502
  if (options.apiUrl) {
1505
1503
  this._apiUrl = options.apiUrl.replace(/\/$/, "");
1506
1504
  } else {
1507
- const effectiveRegion = options.region || detectedRegion || "eu";
1508
- if (!(effectiveRegion in REGION_URLS)) {
1505
+ const effectiveRegion = options.region || detectedRegion;
1506
+ if (!effectiveRegion) {
1507
+ this._apiUrl = DEFAULT_API_URL;
1508
+ } else if (!SUPPORTED_REGIONS.includes(effectiveRegion)) {
1509
1509
  throw new ValidationError(
1510
- `Invalid region '${effectiveRegion}'. Must be one of: ${Object.keys(REGION_URLS).join(", ")}.`
1510
+ `Invalid region '${effectiveRegion}'. Must be one of: ${SUPPORTED_REGIONS.join(", ")}.`
1511
1511
  );
1512
+ } else {
1513
+ this._apiUrl = effectiveRegion === "eu" ? EU_API_URL : DEFAULT_API_URL;
1512
1514
  }
1513
- this._apiUrl = REGION_URLS[effectiveRegion];
1514
1515
  }
1515
1516
  this._ttsUrl = (options.ttsUrl || this._apiUrl).replace(/\/$/, "");
1516
1517
  this._timeout = options.timeout || 6e4;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kugelaudio",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for KugelAudio TTS API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -58,4 +58,4 @@
58
58
  "tsx": "^4.21.0",
59
59
  "ws": "^8.18.0"
60
60
  }
61
- }
61
+ }
@@ -180,42 +180,42 @@ describe('TTSResource.toReadable()', () => {
180
180
  // ---------------------------------------------------------------------------
181
181
 
182
182
  describe('KugelAudio multi-region', () => {
183
- it('defaults to EU when no region or prefix is given', () => {
183
+ it('uses canonical API when no region or prefix is given', () => {
184
184
  const client = new KugelAudio({ apiKey: 'ka_test123' });
185
185
  expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
186
186
  });
187
187
 
188
- it('selects US endpoint with explicit region', () => {
188
+ it('selects canonical endpoint with explicit region', () => {
189
189
  const client = new KugelAudio({ apiKey: 'ka_test123', region: 'us' });
190
- expect((client as any)._apiUrl).toBe('https://us-api.kugelaudio.com');
190
+ expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
191
191
  });
192
192
 
193
193
  it('selects global endpoint with explicit region', () => {
194
194
  const client = new KugelAudio({ apiKey: 'ka_test123', region: 'global' });
195
- expect((client as any)._apiUrl).toBe('https://global-api.kugelaudio.com');
195
+ expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
196
196
  });
197
197
 
198
- it('detects US region from key prefix and strips it', () => {
198
+ it('detects canonical route from key prefix and strips it', () => {
199
199
  const client = new KugelAudio({ apiKey: 'us-ka_test123' });
200
- expect((client as any)._apiUrl).toBe('https://us-api.kugelaudio.com');
200
+ expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
201
201
  expect((client as any)._apiKey).toBe('ka_test123');
202
202
  });
203
203
 
204
204
  it('detects global region from key prefix and strips it', () => {
205
205
  const client = new KugelAudio({ apiKey: 'global-ka_test123' });
206
- expect((client as any)._apiUrl).toBe('https://global-api.kugelaudio.com');
206
+ expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
207
207
  expect((client as any)._apiKey).toBe('ka_test123');
208
208
  });
209
209
 
210
210
  it('detects EU region from key prefix and strips it', () => {
211
211
  const client = new KugelAudio({ apiKey: 'eu-ka_test123' });
212
- expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
212
+ expect((client as any)._apiUrl).toBe('https://api.eu.kugelaudio.com');
213
213
  expect((client as any)._apiKey).toBe('ka_test123');
214
214
  });
215
215
 
216
216
  it('explicit region overrides key prefix', () => {
217
217
  const client = new KugelAudio({ apiKey: 'us-ka_test123', region: 'global' });
218
- expect((client as any)._apiUrl).toBe('https://global-api.kugelaudio.com');
218
+ expect((client as any)._apiUrl).toBe('https://api.kugelaudio.com');
219
219
  expect((client as any)._apiKey).toBe('ka_test123');
220
220
  });
221
221
 
@@ -237,7 +237,7 @@ describe('KugelAudio multi-region', () => {
237
237
 
238
238
  it('ttsUrl defaults to the resolved region URL', () => {
239
239
  const client = new KugelAudio({ apiKey: 'us-ka_test123' });
240
- expect((client as any)._ttsUrl).toBe('https://us-api.kugelaudio.com');
240
+ expect((client as any)._ttsUrl).toBe('https://api.kugelaudio.com');
241
241
  });
242
242
 
243
243
  it('unprefixed key is not modified', () => {
package/src/client.ts CHANGED
@@ -33,11 +33,9 @@ import { getWebSocket } from './websocket';
33
33
 
34
34
  import type { Region } from './types';
35
35
 
36
- const REGION_URLS: Record<Region, string> = {
37
- eu: 'https://api.kugelaudio.com',
38
- us: 'https://us-api.kugelaudio.com',
39
- global: 'https://global-api.kugelaudio.com',
40
- };
36
+ const DEFAULT_API_URL = 'https://api.kugelaudio.com';
37
+ const EU_API_URL = 'https://api.eu.kugelaudio.com';
38
+ const SUPPORTED_REGIONS = ['eu', 'us', 'global'] as const;
41
39
 
42
40
  const REGION_PREFIXES = ['eu-', 'us-', 'global-'] as const;
43
41
 
@@ -1637,13 +1635,16 @@ export class KugelAudio {
1637
1635
  if (options.apiUrl) {
1638
1636
  this._apiUrl = options.apiUrl.replace(/\/$/, '');
1639
1637
  } else {
1640
- const effectiveRegion = options.region || detectedRegion || 'eu';
1641
- if (!(effectiveRegion in REGION_URLS)) {
1638
+ const effectiveRegion = options.region || detectedRegion;
1639
+ if (!effectiveRegion) {
1640
+ this._apiUrl = DEFAULT_API_URL;
1641
+ } else if (!SUPPORTED_REGIONS.includes(effectiveRegion as Region)) {
1642
1642
  throw new ValidationError(
1643
- `Invalid region '${effectiveRegion}'. Must be one of: ${Object.keys(REGION_URLS).join(', ')}.`,
1643
+ `Invalid region '${effectiveRegion}'. Must be one of: ${SUPPORTED_REGIONS.join(', ')}.`,
1644
1644
  );
1645
+ } else {
1646
+ this._apiUrl = effectiveRegion === 'eu' ? EU_API_URL : DEFAULT_API_URL;
1645
1647
  }
1646
- this._apiUrl = REGION_URLS[effectiveRegion as Region];
1647
1648
  }
1648
1649
 
1649
1650
  // If ttsUrl not specified, use apiUrl (backend proxies to TTS server)
@@ -1843,4 +1844,3 @@ export class KugelAudio {
1843
1844
  }
1844
1845
  }
1845
1846
  }
1846
-
package/src/types.ts CHANGED
@@ -399,10 +399,10 @@ export interface StreamCallbacks {
399
399
  }
400
400
 
401
401
  /**
402
- * Deployment region. Controls which API endpoint the SDK connects to.
403
- * - `'eu'` — `api.kugelaudio.com` (default)
404
- * - `'us'` — `us-api.kugelaudio.com`
405
- * - `'global'` `global-api.kugelaudio.com` (geo-routed)
402
+ * Deployment region. Set `'eu'` to use the direct EU endpoint:
403
+ * `api.eu.kugelaudio.com`.
404
+ *
405
+ * If omitted, the SDK uses `api.kugelaudio.com`.
406
406
  */
407
407
  export type Region = 'eu' | 'us' | 'global';
408
408
 
@@ -410,7 +410,7 @@ export type Region = 'eu' | 'us' | 'global';
410
410
  * KugelAudio client options.
411
411
  */
412
412
  export interface KugelAudioOptions {
413
- /** Your KugelAudio API key or JWT token. Can be prefixed with `eu-`, `us-`, or `global-` to select a region (prefix is stripped before auth). */
413
+ /** Your KugelAudio API key or JWT token. Prefix with `eu-` to select the direct EU endpoint (prefix is stripped before auth). */
414
414
  apiKey: string;
415
415
  /** Whether apiKey is a master key (for internal/server-side use). Master keys bypass billing. */
416
416
  isMasterKey?: boolean;
@@ -418,7 +418,7 @@ export interface KugelAudioOptions {
418
418
  isToken?: boolean;
419
419
  /** Organisation ID to bill usage against (required for token auth to enable usage recording). */
420
420
  orgId?: number;
421
- /** Deployment region. Takes precedence over API-key prefix but not over `apiUrl`. */
421
+ /** Deployment region. Set `eu` to select the direct EU endpoint. Takes precedence over API-key prefix but not over `apiUrl`. */
422
422
  region?: Region;
423
423
  /** API base URL (default: https://api.kugelaudio.com) */
424
424
  apiUrl?: string;
@@ -515,4 +515,3 @@ export interface MultiContextCallbacks {
515
515
  /** Called on error */
516
516
  onError?: (error: Error, contextId?: string) => void;
517
517
  }
518
-