kugelaudio 0.6.1 → 0.7.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 +11 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +84 -7
- package/dist/index.mjs +84 -7
- package/package.json +1 -1
- package/src/client.test.ts +41 -1
- package/src/client.ts +22 -5
- package/src/types.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## [kugelaudio-v0.7.0](https://github.com/Kugelaudio/KugelAudio/compare/js-sdk-v0.6.1...js-sdk-v0.7.0) (2026-06-06)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **ingress:** add request observability metadata ([#1321](https://github.com/Kugelaudio/KugelAudio/issues/1321)) ([a9c5178](https://github.com/Kugelaudio/KugelAudio/commit/a9c5178193cb8b746a8bbd9b566b11f7b1d00f6d))
|
|
6
|
+
* **sdks:** default all SDKs to kugel-3 model ([#1323](https://github.com/Kugelaudio/KugelAudio/issues/1323)) ([c4de212](https://github.com/Kugelaudio/KugelAudio/commit/c4de212c91e16326a15dbee5622acacc83ed85bb))
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **js-sdk:** type SDK metadata fetch mock ([#1334](https://github.com/Kugelaudio/KugelAudio/issues/1334)) ([e8f6f59](https://github.com/Kugelaudio/KugelAudio/commit/e8f6f59595e123eaae8b44670c94fb4e7bc8d06c))
|
|
11
|
+
|
|
1
12
|
## [kugelaudio-v0.6.1](https://github.com/Kugelaudio/KugelAudio/compare/js-sdk-v0.6.0...js-sdk-v0.6.1) (2026-06-04)
|
|
2
13
|
|
|
3
14
|
### Bug Fixes
|
package/dist/index.d.mts
CHANGED
|
@@ -217,7 +217,7 @@ interface WordTimestamp {
|
|
|
217
217
|
interface GenerateOptions {
|
|
218
218
|
/** Text to synthesize */
|
|
219
219
|
text: string;
|
|
220
|
-
/** Model to use: 'kugel-
|
|
220
|
+
/** Model to use. Default: 'kugel-3'. Legacy ids (kugel-2.5, kugel-1-turbo, …) still accepted; they alias to kugel-3 server-side. */
|
|
221
221
|
modelId?: string;
|
|
222
222
|
/** Voice ID to use */
|
|
223
223
|
voiceId?: number;
|
|
@@ -296,7 +296,7 @@ interface GenerateOptions {
|
|
|
296
296
|
interface StreamConfig {
|
|
297
297
|
/** Voice ID to use */
|
|
298
298
|
voiceId?: number;
|
|
299
|
-
/** Model ID
|
|
299
|
+
/** Model ID. Default: 'kugel-3'. Legacy ids still accepted; they alias to kugel-3 server-side. */
|
|
300
300
|
modelId?: string;
|
|
301
301
|
/** CFG scale for generation */
|
|
302
302
|
cfgScale?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -217,7 +217,7 @@ interface WordTimestamp {
|
|
|
217
217
|
interface GenerateOptions {
|
|
218
218
|
/** Text to synthesize */
|
|
219
219
|
text: string;
|
|
220
|
-
/** Model to use: 'kugel-
|
|
220
|
+
/** Model to use. Default: 'kugel-3'. Legacy ids (kugel-2.5, kugel-1-turbo, …) still accepted; they alias to kugel-3 server-side. */
|
|
221
221
|
modelId?: string;
|
|
222
222
|
/** Voice ID to use */
|
|
223
223
|
voiceId?: number;
|
|
@@ -296,7 +296,7 @@ interface GenerateOptions {
|
|
|
296
296
|
interface StreamConfig {
|
|
297
297
|
/** Voice ID to use */
|
|
298
298
|
voiceId?: number;
|
|
299
|
-
/** Model ID
|
|
299
|
+
/** Model ID. Default: 'kugel-3'. Legacy ids still accepted; they alias to kugel-3 server-side. */
|
|
300
300
|
modelId?: string;
|
|
301
301
|
/** CFG scale for generation */
|
|
302
302
|
cfgScale?: number;
|
package/dist/index.js
CHANGED
|
@@ -512,10 +512,75 @@ function getWebSocket() {
|
|
|
512
512
|
);
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
+
// package.json
|
|
516
|
+
var package_default = {
|
|
517
|
+
name: "kugelaudio",
|
|
518
|
+
version: "0.7.0",
|
|
519
|
+
description: "Official JavaScript/TypeScript SDK for KugelAudio TTS API",
|
|
520
|
+
main: "dist/index.js",
|
|
521
|
+
module: "dist/index.mjs",
|
|
522
|
+
types: "dist/index.d.ts",
|
|
523
|
+
exports: {
|
|
524
|
+
".": {
|
|
525
|
+
types: "./dist/index.d.ts",
|
|
526
|
+
import: "./dist/index.mjs",
|
|
527
|
+
require: "./dist/index.js"
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
files: [
|
|
531
|
+
"dist",
|
|
532
|
+
"src",
|
|
533
|
+
"LICENSE",
|
|
534
|
+
"CHANGELOG.md"
|
|
535
|
+
],
|
|
536
|
+
scripts: {
|
|
537
|
+
build: "tsup src/index.ts --format cjs,esm --dts",
|
|
538
|
+
dev: "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
539
|
+
lint: "eslint src/",
|
|
540
|
+
test: "vitest run",
|
|
541
|
+
"test:watch": "vitest",
|
|
542
|
+
prepublishOnly: "npm run build"
|
|
543
|
+
},
|
|
544
|
+
keywords: [
|
|
545
|
+
"tts",
|
|
546
|
+
"text-to-speech",
|
|
547
|
+
"audio",
|
|
548
|
+
"streaming",
|
|
549
|
+
"websocket",
|
|
550
|
+
"kugelaudio"
|
|
551
|
+
],
|
|
552
|
+
author: "KugelAudio <hello@kugelaudio.com>",
|
|
553
|
+
license: "MIT",
|
|
554
|
+
repository: {
|
|
555
|
+
type: "git",
|
|
556
|
+
url: "https://github.com/Kugelaudio/KugelAudio",
|
|
557
|
+
directory: "sdks/js"
|
|
558
|
+
},
|
|
559
|
+
homepage: "https://kugelaudio.com",
|
|
560
|
+
bugs: {
|
|
561
|
+
url: "https://github.com/Kugelaudio/KugelAudio/issues"
|
|
562
|
+
},
|
|
563
|
+
devDependencies: {
|
|
564
|
+
"@types/node": "^25.3.2",
|
|
565
|
+
tsup: "^8.0.0",
|
|
566
|
+
typescript: "^6.0.2",
|
|
567
|
+
vitest: "^4.0.18"
|
|
568
|
+
},
|
|
569
|
+
engines: {
|
|
570
|
+
node: ">=18.0.0"
|
|
571
|
+
},
|
|
572
|
+
dependencies: {
|
|
573
|
+
tsx: "^4.21.0",
|
|
574
|
+
ws: "^8.18.0"
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
|
|
515
578
|
// src/client.ts
|
|
516
579
|
var DEFAULT_API_URL = "https://api.kugelaudio.com";
|
|
517
580
|
var EU_API_URL = "https://api.eu.kugelaudio.com";
|
|
518
581
|
var SUPPORTED_REGIONS = ["eu", "us", "global"];
|
|
582
|
+
var SDK_NAME = "js";
|
|
583
|
+
var SDK_VERSION = package_default.version;
|
|
519
584
|
var REGION_PREFIXES = ["eu-", "us-", "global-"];
|
|
520
585
|
function parseApiKey(apiKey) {
|
|
521
586
|
for (const prefix of REGION_PREFIXES) {
|
|
@@ -525,6 +590,16 @@ function parseApiKey(apiKey) {
|
|
|
525
590
|
}
|
|
526
591
|
return { cleanKey: apiKey };
|
|
527
592
|
}
|
|
593
|
+
function sdkHeaders() {
|
|
594
|
+
return {
|
|
595
|
+
"X-KugelAudio-SDK": SDK_NAME,
|
|
596
|
+
"X-KugelAudio-SDK-Version": SDK_VERSION
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function appendSdkQuery(url) {
|
|
600
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
601
|
+
return `${url}${separator}sdk=${encodeURIComponent(SDK_NAME)}&sdk_version=${encodeURIComponent(SDK_VERSION)}`;
|
|
602
|
+
}
|
|
528
603
|
function createWs(url) {
|
|
529
604
|
const WS = getWebSocket();
|
|
530
605
|
return new WS(url);
|
|
@@ -893,7 +968,7 @@ var TTSResource = class {
|
|
|
893
968
|
if (this.client.orgId !== void 0) {
|
|
894
969
|
url += `&org_id=${this.client.orgId}`;
|
|
895
970
|
}
|
|
896
|
-
return url;
|
|
971
|
+
return appendSdkQuery(url);
|
|
897
972
|
}
|
|
898
973
|
/**
|
|
899
974
|
* Get or create a WebSocket connection for connection pooling.
|
|
@@ -1041,7 +1116,7 @@ var TTSResource = class {
|
|
|
1041
1116
|
callbacks.onOpen?.();
|
|
1042
1117
|
ws.send(JSON.stringify({
|
|
1043
1118
|
text: options.text,
|
|
1044
|
-
model_id: options.modelId || "kugel-
|
|
1119
|
+
model_id: options.modelId || "kugel-3",
|
|
1045
1120
|
voice_id: options.voiceId,
|
|
1046
1121
|
cfg_scale: options.cfgScale ?? 2,
|
|
1047
1122
|
...options.temperature !== void 0 && { temperature: options.temperature },
|
|
@@ -1067,7 +1142,7 @@ var TTSResource = class {
|
|
|
1067
1142
|
callbacks.onOpen?.();
|
|
1068
1143
|
ws.send(JSON.stringify({
|
|
1069
1144
|
text: options.text,
|
|
1070
|
-
model_id: options.modelId || "kugel-
|
|
1145
|
+
model_id: options.modelId || "kugel-3",
|
|
1071
1146
|
voice_id: options.voiceId,
|
|
1072
1147
|
cfg_scale: options.cfgScale ?? 2,
|
|
1073
1148
|
max_new_tokens: options.maxNewTokens ?? 2048,
|
|
@@ -1297,7 +1372,7 @@ var MultiContextSession = class {
|
|
|
1297
1372
|
} else {
|
|
1298
1373
|
authParam = "api_key";
|
|
1299
1374
|
}
|
|
1300
|
-
const url = `${wsUrl}/ws/tts/multi?${authParam}=${this.client.apiKey}
|
|
1375
|
+
const url = appendSdkQuery(`${wsUrl}/ws/tts/multi?${authParam}=${this.client.apiKey}`);
|
|
1301
1376
|
this.ws = createWs(url);
|
|
1302
1377
|
const ws = this.ws;
|
|
1303
1378
|
ws.onmessage = (event) => {
|
|
@@ -1518,7 +1593,7 @@ var StreamingSession = class {
|
|
|
1518
1593
|
} else {
|
|
1519
1594
|
authParam = "api_key";
|
|
1520
1595
|
}
|
|
1521
|
-
const url = `${wsUrl}/ws/tts/stream?${authParam}=${this.client.apiKey}
|
|
1596
|
+
const url = appendSdkQuery(`${wsUrl}/ws/tts/stream?${authParam}=${this.client.apiKey}`);
|
|
1522
1597
|
this.ws = createWs(url);
|
|
1523
1598
|
const ws = this.ws;
|
|
1524
1599
|
ws.onmessage = (event) => {
|
|
@@ -1922,7 +1997,8 @@ var KugelAudio = class _KugelAudio {
|
|
|
1922
1997
|
const headers = {
|
|
1923
1998
|
"Content-Type": "application/json",
|
|
1924
1999
|
"X-API-Key": this._apiKey,
|
|
1925
|
-
"Authorization": `Bearer ${this._apiKey}
|
|
2000
|
+
"Authorization": `Bearer ${this._apiKey}`,
|
|
2001
|
+
...sdkHeaders()
|
|
1926
2002
|
};
|
|
1927
2003
|
const controller = new AbortController();
|
|
1928
2004
|
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
|
@@ -1962,7 +2038,8 @@ var KugelAudio = class _KugelAudio {
|
|
|
1962
2038
|
const url = `${this._apiUrl}${path}`;
|
|
1963
2039
|
const headers = {
|
|
1964
2040
|
"X-API-Key": this._apiKey,
|
|
1965
|
-
"Authorization": `Bearer ${this._apiKey}
|
|
2041
|
+
"Authorization": `Bearer ${this._apiKey}`,
|
|
2042
|
+
...sdkHeaders()
|
|
1966
2043
|
};
|
|
1967
2044
|
const controller = new AbortController();
|
|
1968
2045
|
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
package/dist/index.mjs
CHANGED
|
@@ -474,10 +474,75 @@ function getWebSocket() {
|
|
|
474
474
|
);
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
+
// package.json
|
|
478
|
+
var package_default = {
|
|
479
|
+
name: "kugelaudio",
|
|
480
|
+
version: "0.7.0",
|
|
481
|
+
description: "Official JavaScript/TypeScript SDK for KugelAudio TTS API",
|
|
482
|
+
main: "dist/index.js",
|
|
483
|
+
module: "dist/index.mjs",
|
|
484
|
+
types: "dist/index.d.ts",
|
|
485
|
+
exports: {
|
|
486
|
+
".": {
|
|
487
|
+
types: "./dist/index.d.ts",
|
|
488
|
+
import: "./dist/index.mjs",
|
|
489
|
+
require: "./dist/index.js"
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
files: [
|
|
493
|
+
"dist",
|
|
494
|
+
"src",
|
|
495
|
+
"LICENSE",
|
|
496
|
+
"CHANGELOG.md"
|
|
497
|
+
],
|
|
498
|
+
scripts: {
|
|
499
|
+
build: "tsup src/index.ts --format cjs,esm --dts",
|
|
500
|
+
dev: "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
501
|
+
lint: "eslint src/",
|
|
502
|
+
test: "vitest run",
|
|
503
|
+
"test:watch": "vitest",
|
|
504
|
+
prepublishOnly: "npm run build"
|
|
505
|
+
},
|
|
506
|
+
keywords: [
|
|
507
|
+
"tts",
|
|
508
|
+
"text-to-speech",
|
|
509
|
+
"audio",
|
|
510
|
+
"streaming",
|
|
511
|
+
"websocket",
|
|
512
|
+
"kugelaudio"
|
|
513
|
+
],
|
|
514
|
+
author: "KugelAudio <hello@kugelaudio.com>",
|
|
515
|
+
license: "MIT",
|
|
516
|
+
repository: {
|
|
517
|
+
type: "git",
|
|
518
|
+
url: "https://github.com/Kugelaudio/KugelAudio",
|
|
519
|
+
directory: "sdks/js"
|
|
520
|
+
},
|
|
521
|
+
homepage: "https://kugelaudio.com",
|
|
522
|
+
bugs: {
|
|
523
|
+
url: "https://github.com/Kugelaudio/KugelAudio/issues"
|
|
524
|
+
},
|
|
525
|
+
devDependencies: {
|
|
526
|
+
"@types/node": "^25.3.2",
|
|
527
|
+
tsup: "^8.0.0",
|
|
528
|
+
typescript: "^6.0.2",
|
|
529
|
+
vitest: "^4.0.18"
|
|
530
|
+
},
|
|
531
|
+
engines: {
|
|
532
|
+
node: ">=18.0.0"
|
|
533
|
+
},
|
|
534
|
+
dependencies: {
|
|
535
|
+
tsx: "^4.21.0",
|
|
536
|
+
ws: "^8.18.0"
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
|
|
477
540
|
// src/client.ts
|
|
478
541
|
var DEFAULT_API_URL = "https://api.kugelaudio.com";
|
|
479
542
|
var EU_API_URL = "https://api.eu.kugelaudio.com";
|
|
480
543
|
var SUPPORTED_REGIONS = ["eu", "us", "global"];
|
|
544
|
+
var SDK_NAME = "js";
|
|
545
|
+
var SDK_VERSION = package_default.version;
|
|
481
546
|
var REGION_PREFIXES = ["eu-", "us-", "global-"];
|
|
482
547
|
function parseApiKey(apiKey) {
|
|
483
548
|
for (const prefix of REGION_PREFIXES) {
|
|
@@ -487,6 +552,16 @@ function parseApiKey(apiKey) {
|
|
|
487
552
|
}
|
|
488
553
|
return { cleanKey: apiKey };
|
|
489
554
|
}
|
|
555
|
+
function sdkHeaders() {
|
|
556
|
+
return {
|
|
557
|
+
"X-KugelAudio-SDK": SDK_NAME,
|
|
558
|
+
"X-KugelAudio-SDK-Version": SDK_VERSION
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
function appendSdkQuery(url) {
|
|
562
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
563
|
+
return `${url}${separator}sdk=${encodeURIComponent(SDK_NAME)}&sdk_version=${encodeURIComponent(SDK_VERSION)}`;
|
|
564
|
+
}
|
|
490
565
|
function createWs(url) {
|
|
491
566
|
const WS = getWebSocket();
|
|
492
567
|
return new WS(url);
|
|
@@ -855,7 +930,7 @@ var TTSResource = class {
|
|
|
855
930
|
if (this.client.orgId !== void 0) {
|
|
856
931
|
url += `&org_id=${this.client.orgId}`;
|
|
857
932
|
}
|
|
858
|
-
return url;
|
|
933
|
+
return appendSdkQuery(url);
|
|
859
934
|
}
|
|
860
935
|
/**
|
|
861
936
|
* Get or create a WebSocket connection for connection pooling.
|
|
@@ -1003,7 +1078,7 @@ var TTSResource = class {
|
|
|
1003
1078
|
callbacks.onOpen?.();
|
|
1004
1079
|
ws.send(JSON.stringify({
|
|
1005
1080
|
text: options.text,
|
|
1006
|
-
model_id: options.modelId || "kugel-
|
|
1081
|
+
model_id: options.modelId || "kugel-3",
|
|
1007
1082
|
voice_id: options.voiceId,
|
|
1008
1083
|
cfg_scale: options.cfgScale ?? 2,
|
|
1009
1084
|
...options.temperature !== void 0 && { temperature: options.temperature },
|
|
@@ -1029,7 +1104,7 @@ var TTSResource = class {
|
|
|
1029
1104
|
callbacks.onOpen?.();
|
|
1030
1105
|
ws.send(JSON.stringify({
|
|
1031
1106
|
text: options.text,
|
|
1032
|
-
model_id: options.modelId || "kugel-
|
|
1107
|
+
model_id: options.modelId || "kugel-3",
|
|
1033
1108
|
voice_id: options.voiceId,
|
|
1034
1109
|
cfg_scale: options.cfgScale ?? 2,
|
|
1035
1110
|
max_new_tokens: options.maxNewTokens ?? 2048,
|
|
@@ -1259,7 +1334,7 @@ var MultiContextSession = class {
|
|
|
1259
1334
|
} else {
|
|
1260
1335
|
authParam = "api_key";
|
|
1261
1336
|
}
|
|
1262
|
-
const url = `${wsUrl}/ws/tts/multi?${authParam}=${this.client.apiKey}
|
|
1337
|
+
const url = appendSdkQuery(`${wsUrl}/ws/tts/multi?${authParam}=${this.client.apiKey}`);
|
|
1263
1338
|
this.ws = createWs(url);
|
|
1264
1339
|
const ws = this.ws;
|
|
1265
1340
|
ws.onmessage = (event) => {
|
|
@@ -1480,7 +1555,7 @@ var StreamingSession = class {
|
|
|
1480
1555
|
} else {
|
|
1481
1556
|
authParam = "api_key";
|
|
1482
1557
|
}
|
|
1483
|
-
const url = `${wsUrl}/ws/tts/stream?${authParam}=${this.client.apiKey}
|
|
1558
|
+
const url = appendSdkQuery(`${wsUrl}/ws/tts/stream?${authParam}=${this.client.apiKey}`);
|
|
1484
1559
|
this.ws = createWs(url);
|
|
1485
1560
|
const ws = this.ws;
|
|
1486
1561
|
ws.onmessage = (event) => {
|
|
@@ -1884,7 +1959,8 @@ var KugelAudio = class _KugelAudio {
|
|
|
1884
1959
|
const headers = {
|
|
1885
1960
|
"Content-Type": "application/json",
|
|
1886
1961
|
"X-API-Key": this._apiKey,
|
|
1887
|
-
"Authorization": `Bearer ${this._apiKey}
|
|
1962
|
+
"Authorization": `Bearer ${this._apiKey}`,
|
|
1963
|
+
...sdkHeaders()
|
|
1888
1964
|
};
|
|
1889
1965
|
const controller = new AbortController();
|
|
1890
1966
|
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
|
@@ -1924,7 +2000,8 @@ var KugelAudio = class _KugelAudio {
|
|
|
1924
2000
|
const url = `${this._apiUrl}${path}`;
|
|
1925
2001
|
const headers = {
|
|
1926
2002
|
"X-API-Key": this._apiKey,
|
|
1927
|
-
"Authorization": `Bearer ${this._apiKey}
|
|
2003
|
+
"Authorization": `Bearer ${this._apiKey}`,
|
|
2004
|
+
...sdkHeaders()
|
|
1928
2005
|
};
|
|
1929
2006
|
const controller = new AbortController();
|
|
1930
2007
|
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
package/package.json
CHANGED
package/src/client.test.ts
CHANGED
|
@@ -18,6 +18,7 @@ type WsListener = (event: { data: string }) => void;
|
|
|
18
18
|
type WsCloseListener = (event: { code: number }) => void;
|
|
19
19
|
|
|
20
20
|
interface MockWs {
|
|
21
|
+
url: string;
|
|
21
22
|
readyState: number;
|
|
22
23
|
onopen: (() => void) | null;
|
|
23
24
|
onmessage: WsListener | null;
|
|
@@ -33,6 +34,7 @@ let mockWs: MockWs;
|
|
|
33
34
|
vi.mock('./websocket', () => ({
|
|
34
35
|
getWebSocket: () => {
|
|
35
36
|
return class MockWebSocket {
|
|
37
|
+
url: string;
|
|
36
38
|
readyState = 0; // CONNECTING
|
|
37
39
|
onopen: (() => void) | null = null;
|
|
38
40
|
onmessage: WsListener | null = null;
|
|
@@ -42,7 +44,8 @@ vi.mock('./websocket', () => ({
|
|
|
42
44
|
close = vi.fn();
|
|
43
45
|
ping = vi.fn();
|
|
44
46
|
|
|
45
|
-
constructor() {
|
|
47
|
+
constructor(url: string) {
|
|
48
|
+
this.url = url;
|
|
46
49
|
mockWs = this as unknown as MockWs;
|
|
47
50
|
// Simulate async open
|
|
48
51
|
setTimeout(() => {
|
|
@@ -247,6 +250,43 @@ describe('KugelAudio multi-region', () => {
|
|
|
247
250
|
});
|
|
248
251
|
});
|
|
249
252
|
|
|
253
|
+
describe('KugelAudio SDK metadata', () => {
|
|
254
|
+
it('adds SDK metadata headers to HTTP requests', async () => {
|
|
255
|
+
const originalFetch = globalThis.fetch;
|
|
256
|
+
const fetchMock = vi.fn<typeof fetch>(async () => ({
|
|
257
|
+
ok: true,
|
|
258
|
+
json: async () => ({ models: [] }),
|
|
259
|
+
} as Response));
|
|
260
|
+
globalThis.fetch = fetchMock;
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
const client = new KugelAudio({ apiKey: 'ka_test123' });
|
|
264
|
+
await client.models.list();
|
|
265
|
+
} finally {
|
|
266
|
+
globalThis.fetch = originalFetch;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
270
|
+
const [, init] = fetchMock.mock.calls[0];
|
|
271
|
+
expect(init).toMatchObject({
|
|
272
|
+
headers: {
|
|
273
|
+
'X-KugelAudio-SDK': 'js',
|
|
274
|
+
'X-KugelAudio-SDK-Version': '0.6.1',
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('adds SDK metadata query params to WebSocket URLs', async () => {
|
|
280
|
+
const client = new KugelAudio({ apiKey: 'ka_test123' });
|
|
281
|
+
|
|
282
|
+
client.tts.toReadable({ text: 'metadata test' });
|
|
283
|
+
await new Promise<void>((r) => setTimeout(r, 10));
|
|
284
|
+
|
|
285
|
+
expect(mockWs.url).toContain('sdk=js');
|
|
286
|
+
expect(mockWs.url).toContain('sdk_version=0.6.1');
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
250
290
|
// ---------------------------------------------------------------------------
|
|
251
291
|
// Keepalive ping tests
|
|
252
292
|
// ---------------------------------------------------------------------------
|
package/src/client.ts
CHANGED
|
@@ -33,10 +33,13 @@ import { base64ToArrayBuffer } from './utils';
|
|
|
33
33
|
import { getWebSocket } from './websocket';
|
|
34
34
|
|
|
35
35
|
import type { Region } from './types';
|
|
36
|
+
import packageJson from '../package.json';
|
|
36
37
|
|
|
37
38
|
const DEFAULT_API_URL = 'https://api.kugelaudio.com';
|
|
38
39
|
const EU_API_URL = 'https://api.eu.kugelaudio.com';
|
|
39
40
|
const SUPPORTED_REGIONS = ['eu', 'us', 'global'] as const;
|
|
41
|
+
const SDK_NAME = 'js';
|
|
42
|
+
const SDK_VERSION = packageJson.version;
|
|
40
43
|
|
|
41
44
|
const REGION_PREFIXES = ['eu-', 'us-', 'global-'] as const;
|
|
42
45
|
|
|
@@ -49,6 +52,18 @@ function parseApiKey(apiKey: string): { cleanKey: string; detectedRegion?: Regio
|
|
|
49
52
|
return { cleanKey: apiKey };
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
function sdkHeaders(): Record<string, string> {
|
|
56
|
+
return {
|
|
57
|
+
'X-KugelAudio-SDK': SDK_NAME,
|
|
58
|
+
'X-KugelAudio-SDK-Version': SDK_VERSION,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function appendSdkQuery(url: string): string {
|
|
63
|
+
const separator = url.includes('?') ? '&' : '?';
|
|
64
|
+
return `${url}${separator}sdk=${encodeURIComponent(SDK_NAME)}&sdk_version=${encodeURIComponent(SDK_VERSION)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
/**
|
|
53
68
|
* Create a new WebSocket instance.
|
|
54
69
|
* Lazily resolves the constructor to avoid top-level side-effects
|
|
@@ -491,7 +506,7 @@ class TTSResource {
|
|
|
491
506
|
if (this.client.orgId !== undefined) {
|
|
492
507
|
url += `&org_id=${this.client.orgId}`;
|
|
493
508
|
}
|
|
494
|
-
return url;
|
|
509
|
+
return appendSdkQuery(url);
|
|
495
510
|
}
|
|
496
511
|
|
|
497
512
|
/**
|
|
@@ -692,7 +707,7 @@ class TTSResource {
|
|
|
692
707
|
|
|
693
708
|
ws.send(JSON.stringify({
|
|
694
709
|
text: options.text,
|
|
695
|
-
model_id: options.modelId || 'kugel-
|
|
710
|
+
model_id: options.modelId || 'kugel-3',
|
|
696
711
|
voice_id: options.voiceId,
|
|
697
712
|
cfg_scale: options.cfgScale ?? 2.0,
|
|
698
713
|
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
@@ -724,7 +739,7 @@ class TTSResource {
|
|
|
724
739
|
// Send TTS request
|
|
725
740
|
ws.send(JSON.stringify({
|
|
726
741
|
text: options.text,
|
|
727
|
-
model_id: options.modelId || 'kugel-
|
|
742
|
+
model_id: options.modelId || 'kugel-3',
|
|
728
743
|
voice_id: options.voiceId,
|
|
729
744
|
cfg_scale: options.cfgScale ?? 2.0,
|
|
730
745
|
max_new_tokens: options.maxNewTokens ?? 2048,
|
|
@@ -1003,7 +1018,7 @@ class MultiContextSession {
|
|
|
1003
1018
|
authParam = 'api_key';
|
|
1004
1019
|
}
|
|
1005
1020
|
|
|
1006
|
-
const url = `${wsUrl}/ws/tts/multi?${authParam}=${this.client.apiKey}
|
|
1021
|
+
const url = appendSdkQuery(`${wsUrl}/ws/tts/multi?${authParam}=${this.client.apiKey}`);
|
|
1007
1022
|
this.ws = createWs(url);
|
|
1008
1023
|
const ws = this.ws;
|
|
1009
1024
|
|
|
@@ -1317,7 +1332,7 @@ class StreamingSession {
|
|
|
1317
1332
|
authParam = 'api_key';
|
|
1318
1333
|
}
|
|
1319
1334
|
|
|
1320
|
-
const url = `${wsUrl}/ws/tts/stream?${authParam}=${this.client.apiKey}
|
|
1335
|
+
const url = appendSdkQuery(`${wsUrl}/ws/tts/stream?${authParam}=${this.client.apiKey}`);
|
|
1321
1336
|
this.ws = createWs(url);
|
|
1322
1337
|
const ws = this.ws;
|
|
1323
1338
|
|
|
@@ -1865,6 +1880,7 @@ export class KugelAudio {
|
|
|
1865
1880
|
'Content-Type': 'application/json',
|
|
1866
1881
|
'X-API-Key': this._apiKey,
|
|
1867
1882
|
'Authorization': `Bearer ${this._apiKey}`,
|
|
1883
|
+
...sdkHeaders(),
|
|
1868
1884
|
};
|
|
1869
1885
|
|
|
1870
1886
|
const controller = new AbortController();
|
|
@@ -1913,6 +1929,7 @@ export class KugelAudio {
|
|
|
1913
1929
|
const headers: Record<string, string> = {
|
|
1914
1930
|
'X-API-Key': this._apiKey,
|
|
1915
1931
|
'Authorization': `Bearer ${this._apiKey}`,
|
|
1932
|
+
...sdkHeaders(),
|
|
1916
1933
|
};
|
|
1917
1934
|
|
|
1918
1935
|
const controller = new AbortController();
|
package/src/types.ts
CHANGED
|
@@ -240,7 +240,7 @@ export interface WordTimestamp {
|
|
|
240
240
|
export interface GenerateOptions {
|
|
241
241
|
/** Text to synthesize */
|
|
242
242
|
text: string;
|
|
243
|
-
/** Model to use: 'kugel-
|
|
243
|
+
/** Model to use. Default: 'kugel-3'. Legacy ids (kugel-2.5, kugel-1-turbo, …) still accepted; they alias to kugel-3 server-side. */
|
|
244
244
|
modelId?: string;
|
|
245
245
|
/** Voice ID to use */
|
|
246
246
|
voiceId?: number;
|
|
@@ -320,7 +320,7 @@ export interface GenerateOptions {
|
|
|
320
320
|
export interface StreamConfig {
|
|
321
321
|
/** Voice ID to use */
|
|
322
322
|
voiceId?: number;
|
|
323
|
-
/** Model ID
|
|
323
|
+
/** Model ID. Default: 'kugel-3'. Legacy ids still accepted; they alias to kugel-3 server-side. */
|
|
324
324
|
modelId?: string;
|
|
325
325
|
/** CFG scale for generation */
|
|
326
326
|
cfgScale?: number;
|