@lokutor/sdk 1.2.2 → 1.3.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/dist/index.d.mts CHANGED
@@ -1,54 +1,87 @@
1
1
  /**
2
2
  * Available voice styles for the Lokutor AI Agent
3
3
  */
4
+ /**
5
+ * Built-in voices.
6
+ *
7
+ * Versa 2.0 names each voice for the language its reference speaker was recorded in: `EN_*` are
8
+ * English speakers, `ESCA_*` Spanish/Catalan. That is a guide to how a voice sounds, not a
9
+ * restriction — the model is zero-shot, so any voice can speak any supported language.
10
+ *
11
+ * The bare `F1`–`M5` values are the Versa 1.x names. They still work: the server maps them onto
12
+ * the matching Versa 2.0 voice, keeping the language family of the call. Prefer the explicit names
13
+ * in new code.
14
+ *
15
+ * This enum is a convenience, not the full set — a cloned voice's id (`clone_…`) is also a valid
16
+ * `voice`, which is why the config fields accept any string.
17
+ */
4
18
  declare enum VoiceStyle {
19
+ EN_F1 = "en_f1",
20
+ EN_F2 = "en_f2",
21
+ EN_F3 = "en_f3",
22
+ EN_F4 = "en_f4",
23
+ EN_F5 = "en_f5",
24
+ EN_M1 = "en_m1",
25
+ EN_M2 = "en_m2",
26
+ EN_M3 = "en_m3",
27
+ EN_M4 = "en_m4",
28
+ EN_M5 = "en_m5",
29
+ ESCA_F1 = "esca_f1",
30
+ ESCA_F2 = "esca_f2",
31
+ ESCA_F3 = "esca_f3",
32
+ ESCA_F4 = "esca_f4",
33
+ ESCA_F5 = "esca_f5",
34
+ ESCA_M1 = "esca_m1",
35
+ ESCA_M2 = "esca_m2",
36
+ ESCA_M3 = "esca_m3",
37
+ ESCA_M4 = "esca_m4",
38
+ ESCA_M5 = "esca_m5",
39
+ /** @deprecated Versa 1.x name, mapped server-side. Use EN_F1 / ESCA_F1. */
5
40
  F1 = "F1",
41
+ /** @deprecated Versa 1.x name, mapped server-side. */
6
42
  F2 = "F2",
43
+ /** @deprecated Versa 1.x name, mapped server-side. */
7
44
  F3 = "F3",
45
+ /** @deprecated Versa 1.x name, mapped server-side. */
8
46
  F4 = "F4",
47
+ /** @deprecated Versa 1.x name, mapped server-side. */
9
48
  F5 = "F5",
49
+ /** @deprecated Versa 1.x name, mapped server-side. */
10
50
  M1 = "M1",
51
+ /** @deprecated Versa 1.x name, mapped server-side. */
11
52
  M2 = "M2",
53
+ /** @deprecated Versa 1.x name, mapped server-side. */
12
54
  M3 = "M3",
55
+ /** @deprecated Versa 1.x name, mapped server-side. */
13
56
  M4 = "M4",
57
+ /** @deprecated Versa 1.x name, mapped server-side. */
14
58
  M5 = "M5"
15
59
  }
16
60
  /**
17
- * Supported languages for speech and text
61
+ * A voice id: one of {@link VoiceStyle}, or any id the API serves — including a cloned voice's
62
+ * `clone_…`. Typed to keep autocomplete on the enum while still accepting a runtime id.
63
+ */
64
+ type VoiceId = VoiceStyle | (string & {});
65
+ /**
66
+ * Languages Lokutor supports.
67
+ *
68
+ * Nine, as of the Versa 2.0 rollout. The previous list carried 32 entries — Japanese, Chinese,
69
+ * Arabic, Russian and more — that no shipped model was trained to speak, and omitted Catalan,
70
+ * Galician and Basque, which it speaks well. Every one of these except English has a trained
71
+ * language token in the model; English is its unmarked base case.
72
+ *
73
+ * `GET /languages` serves the live list; prefer it over hardcoding if you support user choice.
18
74
  */
19
75
  declare enum Language {
20
76
  ENGLISH = "en",
21
77
  SPANISH = "es",
78
+ CATALAN = "ca",
79
+ GALICIAN = "gl",
80
+ BASQUE = "eu",
81
+ PORTUGUESE = "pt",
22
82
  FRENCH = "fr",
23
- GERMAN = "de",
24
83
  ITALIAN = "it",
25
- PORTUGUESE = "pt",
26
- JAPANESE = "ja",
27
- KOREAN = "ko",
28
- CHINESE = "zh",
29
- ARABIC = "ar",
30
- BULGARIAN = "bg",
31
- CROATIAN = "hr",
32
- CZECH = "cs",
33
- DANISH = "da",
34
- DUTCH = "nl",
35
- ESTONIAN = "et",
36
- FINNISH = "fi",
37
- GREEK = "el",
38
- HINDI = "hi",
39
- HUNGARIAN = "hu",
40
- INDONESIAN = "id",
41
- LATVIAN = "lv",
42
- LITHUANIAN = "lt",
43
- POLISH = "pl",
44
- ROMANIAN = "ro",
45
- RUSSIAN = "ru",
46
- SLOVAK = "sk",
47
- SLOVENIAN = "sl",
48
- SWEDISH = "sv",
49
- TURKISH = "tr",
50
- UKRAINIAN = "uk",
51
- VIETNAMESE = "vi"
84
+ GERMAN = "de"
52
85
  }
53
86
  /**
54
87
  * Audio configuration constants
@@ -87,7 +120,7 @@ interface LokutorConfig {
87
120
  */
88
121
  interface SynthesizeOptions {
89
122
  text: string;
90
- voice?: VoiceStyle;
123
+ voice?: VoiceId;
91
124
  language?: Language;
92
125
  speed?: number;
93
126
  steps?: number;
@@ -163,7 +196,7 @@ interface BrowserAudioOptions {
163
196
  */
164
197
  interface VoiceAgentOptions {
165
198
  prompt?: string;
166
- voice?: VoiceStyle;
199
+ voice?: VoiceId;
167
200
  language?: Language;
168
201
  serverUrl?: string;
169
202
  visemes?: boolean;
@@ -302,7 +335,7 @@ declare class VoiceAgentClient {
302
335
  private apiKey;
303
336
  private agentId;
304
337
  prompt: string;
305
- voice: VoiceStyle;
338
+ voice: VoiceId;
306
339
  language: Language;
307
340
  tools: ToolDefinition[];
308
341
  private onTranscription?;
@@ -330,7 +363,7 @@ declare class VoiceAgentClient {
330
363
  private serverUrl;
331
364
  constructor(config: LokutorConfig & {
332
365
  prompt: string;
333
- voice?: VoiceStyle;
366
+ voice?: VoiceId;
334
367
  language?: Language;
335
368
  visemes?: boolean;
336
369
  onVisemes?: (visemes: Viseme[]) => void;
@@ -436,7 +469,7 @@ declare class VoiceAgentClient {
436
469
  /**
437
470
  * Change the voice style mid-conversation
438
471
  */
439
- updateVoice(voice: VoiceStyle): void;
472
+ updateVoice(voice: VoiceId): void;
440
473
  /**
441
474
  * Change the language mid-conversation
442
475
  */
@@ -478,7 +511,7 @@ declare class TTSClient {
478
511
  */
479
512
  synthesize(options: {
480
513
  text: string;
481
- voice?: VoiceStyle;
514
+ voice?: VoiceId;
482
515
  language?: Language;
483
516
  speed?: number;
484
517
  steps?: number;
@@ -869,4 +902,4 @@ declare class ConversationalPanel {
869
902
  private playErrorTone;
870
903
  }
871
904
 
872
- export { AUDIO_CONFIG, type AnalyserConfig, type AudioManager, type BrowserAudioConfig, BrowserAudioManager, type BrowserAudioOptions, ConversationalPanel, type ConversationalPanelConfig, DEFAULT_URLS, type ErrorCode, type HealthStatus, Language, type LanguageInfo, type LokutorConfig, LokutorError, type ModelInfo, NodeAudioManager, STTClient, type ServerConfig, type ServerStatus, SpeechToTextClient, type SpeechToTextOptions, StreamResampler, type SynthesizeOptions, TTSClient, type ToolCall, type ToolDefinition, type TranscribeOptions, type TranscribeResult, type TranscribeSegment, type Viseme, VoiceAgentClient, type VoiceAgentOptions, type VoiceInfo, VoiceStyle, applyLowPassFilter, bytesToPcm16, calculateRMS, float32ToPcm16, isRetryable, normalizeAudio, pcm16ToBytes, pcm16ToFloat32, resample, resampleWithAntiAliasing, simpleConversation, simpleTTS, simpleTranscribe };
905
+ export { AUDIO_CONFIG, type AnalyserConfig, type AudioManager, type BrowserAudioConfig, BrowserAudioManager, type BrowserAudioOptions, ConversationalPanel, type ConversationalPanelConfig, DEFAULT_URLS, type ErrorCode, type HealthStatus, Language, type LanguageInfo, type LokutorConfig, LokutorError, type ModelInfo, NodeAudioManager, STTClient, type ServerConfig, type ServerStatus, SpeechToTextClient, type SpeechToTextOptions, StreamResampler, type SynthesizeOptions, TTSClient, type ToolCall, type ToolDefinition, type TranscribeOptions, type TranscribeResult, type TranscribeSegment, type Viseme, VoiceAgentClient, type VoiceAgentOptions, type VoiceId, type VoiceInfo, VoiceStyle, applyLowPassFilter, bytesToPcm16, calculateRMS, float32ToPcm16, isRetryable, normalizeAudio, pcm16ToBytes, pcm16ToFloat32, resample, resampleWithAntiAliasing, simpleConversation, simpleTTS, simpleTranscribe };
package/dist/index.d.ts CHANGED
@@ -1,54 +1,87 @@
1
1
  /**
2
2
  * Available voice styles for the Lokutor AI Agent
3
3
  */
4
+ /**
5
+ * Built-in voices.
6
+ *
7
+ * Versa 2.0 names each voice for the language its reference speaker was recorded in: `EN_*` are
8
+ * English speakers, `ESCA_*` Spanish/Catalan. That is a guide to how a voice sounds, not a
9
+ * restriction — the model is zero-shot, so any voice can speak any supported language.
10
+ *
11
+ * The bare `F1`–`M5` values are the Versa 1.x names. They still work: the server maps them onto
12
+ * the matching Versa 2.0 voice, keeping the language family of the call. Prefer the explicit names
13
+ * in new code.
14
+ *
15
+ * This enum is a convenience, not the full set — a cloned voice's id (`clone_…`) is also a valid
16
+ * `voice`, which is why the config fields accept any string.
17
+ */
4
18
  declare enum VoiceStyle {
19
+ EN_F1 = "en_f1",
20
+ EN_F2 = "en_f2",
21
+ EN_F3 = "en_f3",
22
+ EN_F4 = "en_f4",
23
+ EN_F5 = "en_f5",
24
+ EN_M1 = "en_m1",
25
+ EN_M2 = "en_m2",
26
+ EN_M3 = "en_m3",
27
+ EN_M4 = "en_m4",
28
+ EN_M5 = "en_m5",
29
+ ESCA_F1 = "esca_f1",
30
+ ESCA_F2 = "esca_f2",
31
+ ESCA_F3 = "esca_f3",
32
+ ESCA_F4 = "esca_f4",
33
+ ESCA_F5 = "esca_f5",
34
+ ESCA_M1 = "esca_m1",
35
+ ESCA_M2 = "esca_m2",
36
+ ESCA_M3 = "esca_m3",
37
+ ESCA_M4 = "esca_m4",
38
+ ESCA_M5 = "esca_m5",
39
+ /** @deprecated Versa 1.x name, mapped server-side. Use EN_F1 / ESCA_F1. */
5
40
  F1 = "F1",
41
+ /** @deprecated Versa 1.x name, mapped server-side. */
6
42
  F2 = "F2",
43
+ /** @deprecated Versa 1.x name, mapped server-side. */
7
44
  F3 = "F3",
45
+ /** @deprecated Versa 1.x name, mapped server-side. */
8
46
  F4 = "F4",
47
+ /** @deprecated Versa 1.x name, mapped server-side. */
9
48
  F5 = "F5",
49
+ /** @deprecated Versa 1.x name, mapped server-side. */
10
50
  M1 = "M1",
51
+ /** @deprecated Versa 1.x name, mapped server-side. */
11
52
  M2 = "M2",
53
+ /** @deprecated Versa 1.x name, mapped server-side. */
12
54
  M3 = "M3",
55
+ /** @deprecated Versa 1.x name, mapped server-side. */
13
56
  M4 = "M4",
57
+ /** @deprecated Versa 1.x name, mapped server-side. */
14
58
  M5 = "M5"
15
59
  }
16
60
  /**
17
- * Supported languages for speech and text
61
+ * A voice id: one of {@link VoiceStyle}, or any id the API serves — including a cloned voice's
62
+ * `clone_…`. Typed to keep autocomplete on the enum while still accepting a runtime id.
63
+ */
64
+ type VoiceId = VoiceStyle | (string & {});
65
+ /**
66
+ * Languages Lokutor supports.
67
+ *
68
+ * Nine, as of the Versa 2.0 rollout. The previous list carried 32 entries — Japanese, Chinese,
69
+ * Arabic, Russian and more — that no shipped model was trained to speak, and omitted Catalan,
70
+ * Galician and Basque, which it speaks well. Every one of these except English has a trained
71
+ * language token in the model; English is its unmarked base case.
72
+ *
73
+ * `GET /languages` serves the live list; prefer it over hardcoding if you support user choice.
18
74
  */
19
75
  declare enum Language {
20
76
  ENGLISH = "en",
21
77
  SPANISH = "es",
78
+ CATALAN = "ca",
79
+ GALICIAN = "gl",
80
+ BASQUE = "eu",
81
+ PORTUGUESE = "pt",
22
82
  FRENCH = "fr",
23
- GERMAN = "de",
24
83
  ITALIAN = "it",
25
- PORTUGUESE = "pt",
26
- JAPANESE = "ja",
27
- KOREAN = "ko",
28
- CHINESE = "zh",
29
- ARABIC = "ar",
30
- BULGARIAN = "bg",
31
- CROATIAN = "hr",
32
- CZECH = "cs",
33
- DANISH = "da",
34
- DUTCH = "nl",
35
- ESTONIAN = "et",
36
- FINNISH = "fi",
37
- GREEK = "el",
38
- HINDI = "hi",
39
- HUNGARIAN = "hu",
40
- INDONESIAN = "id",
41
- LATVIAN = "lv",
42
- LITHUANIAN = "lt",
43
- POLISH = "pl",
44
- ROMANIAN = "ro",
45
- RUSSIAN = "ru",
46
- SLOVAK = "sk",
47
- SLOVENIAN = "sl",
48
- SWEDISH = "sv",
49
- TURKISH = "tr",
50
- UKRAINIAN = "uk",
51
- VIETNAMESE = "vi"
84
+ GERMAN = "de"
52
85
  }
53
86
  /**
54
87
  * Audio configuration constants
@@ -87,7 +120,7 @@ interface LokutorConfig {
87
120
  */
88
121
  interface SynthesizeOptions {
89
122
  text: string;
90
- voice?: VoiceStyle;
123
+ voice?: VoiceId;
91
124
  language?: Language;
92
125
  speed?: number;
93
126
  steps?: number;
@@ -163,7 +196,7 @@ interface BrowserAudioOptions {
163
196
  */
164
197
  interface VoiceAgentOptions {
165
198
  prompt?: string;
166
- voice?: VoiceStyle;
199
+ voice?: VoiceId;
167
200
  language?: Language;
168
201
  serverUrl?: string;
169
202
  visemes?: boolean;
@@ -302,7 +335,7 @@ declare class VoiceAgentClient {
302
335
  private apiKey;
303
336
  private agentId;
304
337
  prompt: string;
305
- voice: VoiceStyle;
338
+ voice: VoiceId;
306
339
  language: Language;
307
340
  tools: ToolDefinition[];
308
341
  private onTranscription?;
@@ -330,7 +363,7 @@ declare class VoiceAgentClient {
330
363
  private serverUrl;
331
364
  constructor(config: LokutorConfig & {
332
365
  prompt: string;
333
- voice?: VoiceStyle;
366
+ voice?: VoiceId;
334
367
  language?: Language;
335
368
  visemes?: boolean;
336
369
  onVisemes?: (visemes: Viseme[]) => void;
@@ -436,7 +469,7 @@ declare class VoiceAgentClient {
436
469
  /**
437
470
  * Change the voice style mid-conversation
438
471
  */
439
- updateVoice(voice: VoiceStyle): void;
472
+ updateVoice(voice: VoiceId): void;
440
473
  /**
441
474
  * Change the language mid-conversation
442
475
  */
@@ -478,7 +511,7 @@ declare class TTSClient {
478
511
  */
479
512
  synthesize(options: {
480
513
  text: string;
481
- voice?: VoiceStyle;
514
+ voice?: VoiceId;
482
515
  language?: Language;
483
516
  speed?: number;
484
517
  steps?: number;
@@ -869,4 +902,4 @@ declare class ConversationalPanel {
869
902
  private playErrorTone;
870
903
  }
871
904
 
872
- export { AUDIO_CONFIG, type AnalyserConfig, type AudioManager, type BrowserAudioConfig, BrowserAudioManager, type BrowserAudioOptions, ConversationalPanel, type ConversationalPanelConfig, DEFAULT_URLS, type ErrorCode, type HealthStatus, Language, type LanguageInfo, type LokutorConfig, LokutorError, type ModelInfo, NodeAudioManager, STTClient, type ServerConfig, type ServerStatus, SpeechToTextClient, type SpeechToTextOptions, StreamResampler, type SynthesizeOptions, TTSClient, type ToolCall, type ToolDefinition, type TranscribeOptions, type TranscribeResult, type TranscribeSegment, type Viseme, VoiceAgentClient, type VoiceAgentOptions, type VoiceInfo, VoiceStyle, applyLowPassFilter, bytesToPcm16, calculateRMS, float32ToPcm16, isRetryable, normalizeAudio, pcm16ToBytes, pcm16ToFloat32, resample, resampleWithAntiAliasing, simpleConversation, simpleTTS, simpleTranscribe };
905
+ export { AUDIO_CONFIG, type AnalyserConfig, type AudioManager, type BrowserAudioConfig, BrowserAudioManager, type BrowserAudioOptions, ConversationalPanel, type ConversationalPanelConfig, DEFAULT_URLS, type ErrorCode, type HealthStatus, Language, type LanguageInfo, type LokutorConfig, LokutorError, type ModelInfo, NodeAudioManager, STTClient, type ServerConfig, type ServerStatus, SpeechToTextClient, type SpeechToTextOptions, StreamResampler, type SynthesizeOptions, TTSClient, type ToolCall, type ToolDefinition, type TranscribeOptions, type TranscribeResult, type TranscribeSegment, type Viseme, VoiceAgentClient, type VoiceAgentOptions, type VoiceId, type VoiceInfo, VoiceStyle, applyLowPassFilter, bytesToPcm16, calculateRMS, float32ToPcm16, isRetryable, normalizeAudio, pcm16ToBytes, pcm16ToFloat32, resample, resampleWithAntiAliasing, simpleConversation, simpleTTS, simpleTranscribe };
package/dist/index.js CHANGED
@@ -51,6 +51,26 @@ module.exports = __toCommonJS(index_exports);
51
51
 
52
52
  // src/types.ts
53
53
  var VoiceStyle = /* @__PURE__ */ ((VoiceStyle2) => {
54
+ VoiceStyle2["EN_F1"] = "en_f1";
55
+ VoiceStyle2["EN_F2"] = "en_f2";
56
+ VoiceStyle2["EN_F3"] = "en_f3";
57
+ VoiceStyle2["EN_F4"] = "en_f4";
58
+ VoiceStyle2["EN_F5"] = "en_f5";
59
+ VoiceStyle2["EN_M1"] = "en_m1";
60
+ VoiceStyle2["EN_M2"] = "en_m2";
61
+ VoiceStyle2["EN_M3"] = "en_m3";
62
+ VoiceStyle2["EN_M4"] = "en_m4";
63
+ VoiceStyle2["EN_M5"] = "en_m5";
64
+ VoiceStyle2["ESCA_F1"] = "esca_f1";
65
+ VoiceStyle2["ESCA_F2"] = "esca_f2";
66
+ VoiceStyle2["ESCA_F3"] = "esca_f3";
67
+ VoiceStyle2["ESCA_F4"] = "esca_f4";
68
+ VoiceStyle2["ESCA_F5"] = "esca_f5";
69
+ VoiceStyle2["ESCA_M1"] = "esca_m1";
70
+ VoiceStyle2["ESCA_M2"] = "esca_m2";
71
+ VoiceStyle2["ESCA_M3"] = "esca_m3";
72
+ VoiceStyle2["ESCA_M4"] = "esca_m4";
73
+ VoiceStyle2["ESCA_M5"] = "esca_m5";
54
74
  VoiceStyle2["F1"] = "F1";
55
75
  VoiceStyle2["F2"] = "F2";
56
76
  VoiceStyle2["F3"] = "F3";
@@ -66,36 +86,13 @@ var VoiceStyle = /* @__PURE__ */ ((VoiceStyle2) => {
66
86
  var Language = /* @__PURE__ */ ((Language2) => {
67
87
  Language2["ENGLISH"] = "en";
68
88
  Language2["SPANISH"] = "es";
89
+ Language2["CATALAN"] = "ca";
90
+ Language2["GALICIAN"] = "gl";
91
+ Language2["BASQUE"] = "eu";
92
+ Language2["PORTUGUESE"] = "pt";
69
93
  Language2["FRENCH"] = "fr";
70
- Language2["GERMAN"] = "de";
71
94
  Language2["ITALIAN"] = "it";
72
- Language2["PORTUGUESE"] = "pt";
73
- Language2["JAPANESE"] = "ja";
74
- Language2["KOREAN"] = "ko";
75
- Language2["CHINESE"] = "zh";
76
- Language2["ARABIC"] = "ar";
77
- Language2["BULGARIAN"] = "bg";
78
- Language2["CROATIAN"] = "hr";
79
- Language2["CZECH"] = "cs";
80
- Language2["DANISH"] = "da";
81
- Language2["DUTCH"] = "nl";
82
- Language2["ESTONIAN"] = "et";
83
- Language2["FINNISH"] = "fi";
84
- Language2["GREEK"] = "el";
85
- Language2["HINDI"] = "hi";
86
- Language2["HUNGARIAN"] = "hu";
87
- Language2["INDONESIAN"] = "id";
88
- Language2["LATVIAN"] = "lv";
89
- Language2["LITHUANIAN"] = "lt";
90
- Language2["POLISH"] = "pl";
91
- Language2["ROMANIAN"] = "ro";
92
- Language2["RUSSIAN"] = "ru";
93
- Language2["SLOVAK"] = "sk";
94
- Language2["SLOVENIAN"] = "sl";
95
- Language2["SWEDISH"] = "sv";
96
- Language2["TURKISH"] = "tr";
97
- Language2["UKRAINIAN"] = "uk";
98
- Language2["VIETNAMESE"] = "vi";
95
+ Language2["GERMAN"] = "de";
99
96
  return Language2;
100
97
  })(Language || {});
101
98
  var AUDIO_CONFIG = {
@@ -1318,7 +1315,7 @@ var TTSClient = class {
1318
1315
  const req = {
1319
1316
  text: options.text,
1320
1317
  voice: options.voice || "F1" /* F1 */,
1321
- lang: options.language || "en" /* ENGLISH */,
1318
+ language: options.language || "en" /* ENGLISH */,
1322
1319
  speed: options.speed || 1.05,
1323
1320
  steps: options.steps || 24,
1324
1321
  visemes: options.visemes || false
@@ -1407,7 +1404,7 @@ var STTClient = class {
1407
1404
  if (typeof Blob !== "undefined" && options.audio instanceof Blob) {
1408
1405
  const form = new FormData();
1409
1406
  form.append("audio", options.audio, "audio.wav");
1410
- if (options.language) form.append("lang", options.language);
1407
+ if (options.language) form.append("language", options.language);
1411
1408
  if (options.sampleRate) form.append("sample_rate", String(options.sampleRate));
1412
1409
  res = await fetch(url, {
1413
1410
  method: "POST",
@@ -1423,7 +1420,7 @@ var STTClient = class {
1423
1420
  audio: uint8ArrayToBase64(bytes),
1424
1421
  format: options.format || "pcm16",
1425
1422
  sample_rate: options.sampleRate,
1426
- lang: options.language
1423
+ language: options.language
1427
1424
  })
1428
1425
  });
1429
1426
  }
@@ -1495,7 +1492,7 @@ var SpeechToTextClient = class {
1495
1492
  this.ws.onopen = async () => {
1496
1493
  this.isConnected = true;
1497
1494
  this.onStatusChange?.("connected");
1498
- this.ws.send(JSON.stringify({ lang: this.language || "en" /* ENGLISH */, vad: this.vad }));
1495
+ this.ws.send(JSON.stringify({ language: this.language || "en" /* ENGLISH */, vad: this.vad }));
1499
1496
  await this.audioManager.startMicrophone((data) => {
1500
1497
  if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
1501
1498
  this.ws.send(data);
package/dist/index.mjs CHANGED
@@ -1,5 +1,25 @@
1
1
  // src/types.ts
2
2
  var VoiceStyle = /* @__PURE__ */ ((VoiceStyle2) => {
3
+ VoiceStyle2["EN_F1"] = "en_f1";
4
+ VoiceStyle2["EN_F2"] = "en_f2";
5
+ VoiceStyle2["EN_F3"] = "en_f3";
6
+ VoiceStyle2["EN_F4"] = "en_f4";
7
+ VoiceStyle2["EN_F5"] = "en_f5";
8
+ VoiceStyle2["EN_M1"] = "en_m1";
9
+ VoiceStyle2["EN_M2"] = "en_m2";
10
+ VoiceStyle2["EN_M3"] = "en_m3";
11
+ VoiceStyle2["EN_M4"] = "en_m4";
12
+ VoiceStyle2["EN_M5"] = "en_m5";
13
+ VoiceStyle2["ESCA_F1"] = "esca_f1";
14
+ VoiceStyle2["ESCA_F2"] = "esca_f2";
15
+ VoiceStyle2["ESCA_F3"] = "esca_f3";
16
+ VoiceStyle2["ESCA_F4"] = "esca_f4";
17
+ VoiceStyle2["ESCA_F5"] = "esca_f5";
18
+ VoiceStyle2["ESCA_M1"] = "esca_m1";
19
+ VoiceStyle2["ESCA_M2"] = "esca_m2";
20
+ VoiceStyle2["ESCA_M3"] = "esca_m3";
21
+ VoiceStyle2["ESCA_M4"] = "esca_m4";
22
+ VoiceStyle2["ESCA_M5"] = "esca_m5";
3
23
  VoiceStyle2["F1"] = "F1";
4
24
  VoiceStyle2["F2"] = "F2";
5
25
  VoiceStyle2["F3"] = "F3";
@@ -15,36 +35,13 @@ var VoiceStyle = /* @__PURE__ */ ((VoiceStyle2) => {
15
35
  var Language = /* @__PURE__ */ ((Language2) => {
16
36
  Language2["ENGLISH"] = "en";
17
37
  Language2["SPANISH"] = "es";
38
+ Language2["CATALAN"] = "ca";
39
+ Language2["GALICIAN"] = "gl";
40
+ Language2["BASQUE"] = "eu";
41
+ Language2["PORTUGUESE"] = "pt";
18
42
  Language2["FRENCH"] = "fr";
19
- Language2["GERMAN"] = "de";
20
43
  Language2["ITALIAN"] = "it";
21
- Language2["PORTUGUESE"] = "pt";
22
- Language2["JAPANESE"] = "ja";
23
- Language2["KOREAN"] = "ko";
24
- Language2["CHINESE"] = "zh";
25
- Language2["ARABIC"] = "ar";
26
- Language2["BULGARIAN"] = "bg";
27
- Language2["CROATIAN"] = "hr";
28
- Language2["CZECH"] = "cs";
29
- Language2["DANISH"] = "da";
30
- Language2["DUTCH"] = "nl";
31
- Language2["ESTONIAN"] = "et";
32
- Language2["FINNISH"] = "fi";
33
- Language2["GREEK"] = "el";
34
- Language2["HINDI"] = "hi";
35
- Language2["HUNGARIAN"] = "hu";
36
- Language2["INDONESIAN"] = "id";
37
- Language2["LATVIAN"] = "lv";
38
- Language2["LITHUANIAN"] = "lt";
39
- Language2["POLISH"] = "pl";
40
- Language2["ROMANIAN"] = "ro";
41
- Language2["RUSSIAN"] = "ru";
42
- Language2["SLOVAK"] = "sk";
43
- Language2["SLOVENIAN"] = "sl";
44
- Language2["SWEDISH"] = "sv";
45
- Language2["TURKISH"] = "tr";
46
- Language2["UKRAINIAN"] = "uk";
47
- Language2["VIETNAMESE"] = "vi";
44
+ Language2["GERMAN"] = "de";
48
45
  return Language2;
49
46
  })(Language || {});
50
47
  var AUDIO_CONFIG = {
@@ -1267,7 +1264,7 @@ var TTSClient = class {
1267
1264
  const req = {
1268
1265
  text: options.text,
1269
1266
  voice: options.voice || "F1" /* F1 */,
1270
- lang: options.language || "en" /* ENGLISH */,
1267
+ language: options.language || "en" /* ENGLISH */,
1271
1268
  speed: options.speed || 1.05,
1272
1269
  steps: options.steps || 24,
1273
1270
  visemes: options.visemes || false
@@ -1356,7 +1353,7 @@ var STTClient = class {
1356
1353
  if (typeof Blob !== "undefined" && options.audio instanceof Blob) {
1357
1354
  const form = new FormData();
1358
1355
  form.append("audio", options.audio, "audio.wav");
1359
- if (options.language) form.append("lang", options.language);
1356
+ if (options.language) form.append("language", options.language);
1360
1357
  if (options.sampleRate) form.append("sample_rate", String(options.sampleRate));
1361
1358
  res = await fetch(url, {
1362
1359
  method: "POST",
@@ -1372,7 +1369,7 @@ var STTClient = class {
1372
1369
  audio: uint8ArrayToBase64(bytes),
1373
1370
  format: options.format || "pcm16",
1374
1371
  sample_rate: options.sampleRate,
1375
- lang: options.language
1372
+ language: options.language
1376
1373
  })
1377
1374
  });
1378
1375
  }
@@ -1444,7 +1441,7 @@ var SpeechToTextClient = class {
1444
1441
  this.ws.onopen = async () => {
1445
1442
  this.isConnected = true;
1446
1443
  this.onStatusChange?.("connected");
1447
- this.ws.send(JSON.stringify({ lang: this.language || "en" /* ENGLISH */, vad: this.vad }));
1444
+ this.ws.send(JSON.stringify({ language: this.language || "en" /* ENGLISH */, vad: this.vad }));
1448
1445
  await this.audioManager.startMicrophone((data) => {
1449
1446
  if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
1450
1447
  this.ws.send(data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokutor/sdk",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "JavaScript/TypeScript SDK for Lokutor Real-time Voice AI",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
package/src/client.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  VoiceStyle,
3
+ VoiceId,
3
4
  Language,
4
5
  DEFAULT_URLS,
5
6
  LokutorConfig,
@@ -159,7 +160,7 @@ export class VoiceAgentClient {
159
160
  private apiKey: string;
160
161
  private agentId: string = "";
161
162
  public prompt: string;
162
- public voice: VoiceStyle;
163
+ public voice: VoiceId;
163
164
  public language: Language;
164
165
  public tools: ToolDefinition[] = [];
165
166
 
@@ -197,7 +198,7 @@ export class VoiceAgentClient {
197
198
 
198
199
  constructor(config: LokutorConfig & {
199
200
  prompt: string,
200
- voice?: VoiceStyle,
201
+ voice?: VoiceId,
201
202
  language?: Language,
202
203
  visemes?: boolean,
203
204
  onVisemes?: (visemes: Viseme[]) => void,
@@ -208,6 +209,9 @@ export class VoiceAgentClient {
208
209
  this.apiKey = config.apiKey;
209
210
  this.agentId = config.agentId || "";
210
211
  this.prompt = config.prompt;
212
+ // Default stays the Versa 1.x name on purpose: the server resolves F1 to the voice of the
213
+ // call's own language family (esca_f1 for Spanish, en_f1 for English), which adapts better
214
+ // than pinning one explicit voice here would.
211
215
  this.voice = config.voice || VoiceStyle.F1;
212
216
  this.language = config.language || Language.ENGLISH;
213
217
  this.serverUrl = config.serverUrl || DEFAULT_URLS.VOICE_AGENT;
@@ -767,7 +771,7 @@ export class VoiceAgentClient {
767
771
  /**
768
772
  * Change the voice style mid-conversation
769
773
  */
770
- public updateVoice(voice: VoiceStyle) {
774
+ public updateVoice(voice: VoiceId) {
771
775
  this.voice = voice;
772
776
  if (this.ws && this.ws.readyState === WebSocket.OPEN && this.isConnected) {
773
777
  this.ws.send(JSON.stringify({ type: 'voice', data: voice }));
@@ -853,7 +857,7 @@ export class TTSClient {
853
857
  */
854
858
  public synthesize(options: {
855
859
  text: string;
856
- voice?: VoiceStyle;
860
+ voice?: VoiceId;
857
861
  language?: Language;
858
862
  speed?: number;
859
863
  steps?: number;
@@ -893,7 +897,7 @@ export class TTSClient {
893
897
  const req = {
894
898
  text: options.text,
895
899
  voice: options.voice || VoiceStyle.F1,
896
- lang: options.language || Language.ENGLISH,
900
+ language: options.language || Language.ENGLISH,
897
901
  speed: options.speed || 1.05,
898
902
  steps: options.steps || 24,
899
903
  visemes: options.visemes || false
@@ -1001,7 +1005,7 @@ export class STTClient {
1001
1005
  if (typeof Blob !== 'undefined' && options.audio instanceof Blob) {
1002
1006
  const form = new FormData();
1003
1007
  form.append('audio', options.audio, 'audio.wav');
1004
- if (options.language) form.append('lang', options.language);
1008
+ if (options.language) form.append('language', options.language);
1005
1009
  if (options.sampleRate) form.append('sample_rate', String(options.sampleRate));
1006
1010
  res = await fetch(url, {
1007
1011
  method: 'POST',
@@ -1019,7 +1023,7 @@ export class STTClient {
1019
1023
  audio: uint8ArrayToBase64(bytes),
1020
1024
  format: options.format || 'pcm16',
1021
1025
  sample_rate: options.sampleRate,
1022
- lang: options.language,
1026
+ language: options.language,
1023
1027
  }),
1024
1028
  });
1025
1029
  }
@@ -1105,7 +1109,7 @@ export class SpeechToTextClient {
1105
1109
  this.ws.onopen = async () => {
1106
1110
  this.isConnected = true;
1107
1111
  this.onStatusChange?.('connected');
1108
- this.ws!.send(JSON.stringify({ lang: this.language || Language.ENGLISH, vad: this.vad }));
1112
+ this.ws!.send(JSON.stringify({ language: this.language || Language.ENGLISH, vad: this.vad }));
1109
1113
 
1110
1114
  await this.audioManager!.startMicrophone((data) => {
1111
1115
  if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
package/src/types.ts CHANGED
@@ -1,58 +1,93 @@
1
1
  /**
2
2
  * Available voice styles for the Lokutor AI Agent
3
3
  */
4
+ /**
5
+ * Built-in voices.
6
+ *
7
+ * Versa 2.0 names each voice for the language its reference speaker was recorded in: `EN_*` are
8
+ * English speakers, `ESCA_*` Spanish/Catalan. That is a guide to how a voice sounds, not a
9
+ * restriction — the model is zero-shot, so any voice can speak any supported language.
10
+ *
11
+ * The bare `F1`–`M5` values are the Versa 1.x names. They still work: the server maps them onto
12
+ * the matching Versa 2.0 voice, keeping the language family of the call. Prefer the explicit names
13
+ * in new code.
14
+ *
15
+ * This enum is a convenience, not the full set — a cloned voice's id (`clone_…`) is also a valid
16
+ * `voice`, which is why the config fields accept any string.
17
+ */
4
18
  export enum VoiceStyle {
5
- // Female voices
19
+ // English reference speakers
20
+ EN_F1 = "en_f1",
21
+ EN_F2 = "en_f2",
22
+ EN_F3 = "en_f3",
23
+ EN_F4 = "en_f4",
24
+ EN_F5 = "en_f5",
25
+ EN_M1 = "en_m1",
26
+ EN_M2 = "en_m2",
27
+ EN_M3 = "en_m3",
28
+ EN_M4 = "en_m4",
29
+ EN_M5 = "en_m5",
30
+
31
+ // Spanish / Catalan reference speakers
32
+ ESCA_F1 = "esca_f1",
33
+ ESCA_F2 = "esca_f2",
34
+ ESCA_F3 = "esca_f3",
35
+ ESCA_F4 = "esca_f4",
36
+ ESCA_F5 = "esca_f5",
37
+ ESCA_M1 = "esca_m1",
38
+ ESCA_M2 = "esca_m2",
39
+ ESCA_M3 = "esca_m3",
40
+ ESCA_M4 = "esca_m4",
41
+ ESCA_M5 = "esca_m5",
42
+
43
+ /** @deprecated Versa 1.x name, mapped server-side. Use EN_F1 / ESCA_F1. */
6
44
  F1 = "F1",
45
+ /** @deprecated Versa 1.x name, mapped server-side. */
7
46
  F2 = "F2",
47
+ /** @deprecated Versa 1.x name, mapped server-side. */
8
48
  F3 = "F3",
49
+ /** @deprecated Versa 1.x name, mapped server-side. */
9
50
  F4 = "F4",
51
+ /** @deprecated Versa 1.x name, mapped server-side. */
10
52
  F5 = "F5",
11
-
12
- // Male voices
53
+ /** @deprecated Versa 1.x name, mapped server-side. */
13
54
  M1 = "M1",
55
+ /** @deprecated Versa 1.x name, mapped server-side. */
14
56
  M2 = "M2",
57
+ /** @deprecated Versa 1.x name, mapped server-side. */
15
58
  M3 = "M3",
59
+ /** @deprecated Versa 1.x name, mapped server-side. */
16
60
  M4 = "M4",
61
+ /** @deprecated Versa 1.x name, mapped server-side. */
17
62
  M5 = "M5",
18
63
  }
19
64
 
20
65
  /**
21
- * Supported languages for speech and text
66
+ * A voice id: one of {@link VoiceStyle}, or any id the API serves — including a cloned voice's
67
+ * `clone_…`. Typed to keep autocomplete on the enum while still accepting a runtime id.
68
+ */
69
+ export type VoiceId = VoiceStyle | (string & {});
70
+
71
+ /**
72
+ * Languages Lokutor supports.
73
+ *
74
+ * Nine, as of the Versa 2.0 rollout. The previous list carried 32 entries — Japanese, Chinese,
75
+ * Arabic, Russian and more — that no shipped model was trained to speak, and omitted Catalan,
76
+ * Galician and Basque, which it speaks well. Every one of these except English has a trained
77
+ * language token in the model; English is its unmarked base case.
78
+ *
79
+ * `GET /languages` serves the live list; prefer it over hardcoding if you support user choice.
22
80
  */
23
81
  export enum Language {
24
82
  ENGLISH = "en",
25
83
  SPANISH = "es",
84
+ CATALAN = "ca",
85
+ GALICIAN = "gl",
86
+ BASQUE = "eu",
87
+ PORTUGUESE = "pt",
26
88
  FRENCH = "fr",
27
- GERMAN = "de",
28
89
  ITALIAN = "it",
29
- PORTUGUESE = "pt",
30
- JAPANESE = "ja",
31
- KOREAN = "ko",
32
- CHINESE = "zh",
33
- ARABIC = "ar",
34
- BULGARIAN = "bg",
35
- CROATIAN = "hr",
36
- CZECH = "cs",
37
- DANISH = "da",
38
- DUTCH = "nl",
39
- ESTONIAN = "et",
40
- FINNISH = "fi",
41
- GREEK = "el",
42
- HINDI = "hi",
43
- HUNGARIAN = "hu",
44
- INDONESIAN = "id",
45
- LATVIAN = "lv",
46
- LITHUANIAN = "lt",
47
- POLISH = "pl",
48
- ROMANIAN = "ro",
49
- RUSSIAN = "ru",
50
- SLOVAK = "sk",
51
- SLOVENIAN = "sl",
52
- SWEDISH = "sv",
53
- TURKISH = "tr",
54
- UKRAINIAN = "uk",
55
- VIETNAMESE = "vi",
90
+ GERMAN = "de",
56
91
  }
57
92
 
58
93
  /**
@@ -97,7 +132,7 @@ export interface LokutorConfig {
97
132
  */
98
133
  export interface SynthesizeOptions {
99
134
  text: string;
100
- voice?: VoiceStyle;
135
+ voice?: VoiceId;
101
136
  language?: Language;
102
137
  speed?: number;
103
138
  steps?: number;
@@ -179,7 +214,7 @@ export interface BrowserAudioOptions {
179
214
  */
180
215
  export interface VoiceAgentOptions {
181
216
  prompt?: string;
182
- voice?: VoiceStyle;
217
+ voice?: VoiceId;
183
218
  language?: Language;
184
219
  serverUrl?: string;
185
220
  visemes?: boolean;