dvgateway-adapters 1.9.11 → 1.9.13
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/README.md +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/anthropic.d.ts +32 -15
- package/dist/llm/anthropic.d.ts.map +1 -1
- package/dist/llm/anthropic.js +56 -14
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +1 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/openai-llm.d.ts +2 -3
- package/dist/llm/openai-llm.d.ts.map +1 -1
- package/dist/llm/openai-llm.js +2 -3
- package/dist/llm/openai-llm.js.map +1 -1
- package/dist/llm/sampling.test.d.ts +2 -0
- package/dist/llm/sampling.test.d.ts.map +1 -0
- package/dist/llm/sampling.test.js +106 -0
- package/dist/llm/sampling.test.js.map +1 -0
- package/dist/realtime/openai-realtime.d.ts +2 -2
- package/dist/realtime/openai-realtime.js +2 -2
- package/dist/stt/index.d.ts +2 -0
- package/dist/stt/index.d.ts.map +1 -1
- package/dist/stt/index.js +1 -0
- package/dist/stt/index.js.map +1 -1
- package/dist/stt/rtzr.d.ts +80 -0
- package/dist/stt/rtzr.d.ts.map +1 -0
- package/dist/stt/rtzr.js +217 -0
- package/dist/stt/rtzr.js.map +1 -0
- package/dist/stt/rtzr.test.d.ts +2 -0
- package/dist/stt/rtzr.test.d.ts.map +1 -0
- package/dist/stt/rtzr.test.js +102 -0
- package/dist/stt/rtzr.test.js.map +1 -0
- package/dist/tts/elevenlabs.d.ts +3 -3
- package/dist/tts/elevenlabs.js +2 -2
- package/dist/tts/openai-tts.d.ts +3 -3
- package/dist/tts/openai-tts.js +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ npm install dvgateway-sdk dvgateway-adapters
|
|
|
14
14
|
|------|--------|--------|
|
|
15
15
|
| STT | `DeepgramAdapter` | Deepgram Nova-3 |
|
|
16
16
|
| STT | `GoogleChirp3Adapter` | Google Cloud STT Chirp 3 |
|
|
17
|
+
| STT | `RtzrSttAdapter` | 리턴제로 sommers_ko (한국어 전화 음성) |
|
|
17
18
|
| TTS | `ElevenLabsAdapter` | ElevenLabs Flash v2.5 |
|
|
18
19
|
| TTS | `OpenAITtsAdapter` | OpenAI gpt-4o-mini-tts |
|
|
19
20
|
| TTS | `GeminiTtsAdapter` | Google Gemini TTS |
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export { DeepgramAdapter } from './stt/deepgram.js';
|
|
|
26
26
|
export type { DeepgramAdapterOptions } from './stt/deepgram.js';
|
|
27
27
|
export { GoogleChirp3Adapter } from './stt/google-chirp3.js';
|
|
28
28
|
export type { GoogleChirp3AdapterOptions } from './stt/google-chirp3.js';
|
|
29
|
+
export { RtzrSttAdapter } from './stt/rtzr.js';
|
|
30
|
+
export type { RtzrSttAdapterOptions } from './stt/rtzr.js';
|
|
29
31
|
export type { HumanVoiceOptions, SttOptions, TtsOptions, } from 'dvgateway-sdk';
|
|
30
32
|
export { HUMAN_VOICE_DEFAULTS_KO, HUMAN_VOICE_DEFAULTS_EN, } from 'dvgateway-sdk';
|
|
31
33
|
export { ElevenLabsAdapter, ELEVENLABS_KOREAN_VOICES } from './tts/elevenlabs.js';
|
|
@@ -38,7 +40,7 @@ export { GeminiTtsAdapter, GEMINI_TTS_VOICES } from './tts/gemini-tts.js';
|
|
|
38
40
|
export type { GeminiTtsAdapterOptions, GeminiTtsVoice, GeminiTtsModel, } from './tts/gemini-tts.js';
|
|
39
41
|
export { CosyVoiceAdapter, COSYVOICE_VOICES } from './tts/cosyvoice-tts.js';
|
|
40
42
|
export type { CosyVoiceAdapterOptions, CosyVoiceVoice, CosyVoiceModel, } from './tts/cosyvoice-tts.js';
|
|
41
|
-
export { AnthropicAdapter } from './llm/anthropic.js';
|
|
43
|
+
export { AnthropicAdapter, acceptsSamplingParams } from './llm/anthropic.js';
|
|
42
44
|
export type { AnthropicAdapterOptions } from './llm/anthropic.js';
|
|
43
45
|
export { OpenAILlmAdapter } from './llm/openai-llm.js';
|
|
44
46
|
export type { OpenAILlmAdapterOptions } from './llm/openai-llm.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAmB,mBAAmB,CAAC;AACjE,YAAY,EAAE,sBAAsB,EAAE,MAAO,mBAAmB,CAAC;AAEjE,OAAO,EAAE,mBAAmB,EAAE,MAAe,wBAAwB,CAAC;AACtE,YAAY,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAmB,mBAAmB,CAAC;AACjE,YAAY,EAAE,sBAAsB,EAAE,MAAO,mBAAmB,CAAC;AAEjE,OAAO,EAAE,mBAAmB,EAAE,MAAe,wBAAwB,CAAC;AACtE,YAAY,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAoB,eAAe,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAQ,eAAe,CAAC;AAG7D,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,UAAU,GACX,MAA4C,eAAe,CAAC;AAC7D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,GACxB,MAA4C,eAAe,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAClF,YAAY,EAAE,wBAAwB,EAAE,MAAoB,qBAAqB,CAAC;AAElF,OAAO,EAAE,gBAAgB,EAAE,MAAsB,qBAAqB,CAAC;AACvE,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,cAAc,GACf,MAAgD,qBAAqB,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,MAAsB,qBAAqB,CAAC;AACvE,YAAY,EACV,uBAAuB,EACvB,WAAW,GACZ,MAAgD,qBAAqB,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,cAAc,GACf,MAAgD,qBAAqB,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,cAAc,GACf,MAAgD,wBAAwB,CAAC;AAG1E,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,YAAY,EAAE,uBAAuB,EAAE,MAAU,oBAAoB,CAAC;AAEtE,OAAO,EAAE,gBAAgB,EAAE,MAAsB,qBAAqB,CAAC;AACvE,YAAY,EAAE,uBAAuB,EAAE,MAAU,qBAAqB,CAAC;AAEvE,OAAO,EAAE,cAAc,EAAE,MAAwB,kBAAkB,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,MAAY,kBAAkB,CAAC;AAGpE,OAAO,EAAE,qBAAqB,EAAE,MAAiB,+BAA+B,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC9H,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,qBAAqB,GACtB,MAAgD,wBAAwB,CAAC;AAC1E,YAAY,EACV,4BAA4B,EAC5B,mBAAmB,EACnB,+BAA+B,EAC/B,kCAAkC,EAClC,qBAAqB,GACtB,MAAgD,+BAA+B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
// ── STT (Speech-to-Text) ──────────────────────────────────────────────────────
|
|
26
26
|
export { DeepgramAdapter } from './stt/deepgram.js';
|
|
27
27
|
export { GoogleChirp3Adapter } from './stt/google-chirp3.js';
|
|
28
|
+
export { RtzrSttAdapter } from './stt/rtzr.js';
|
|
28
29
|
export { HUMAN_VOICE_DEFAULTS_KO, HUMAN_VOICE_DEFAULTS_EN, } from 'dvgateway-sdk';
|
|
29
30
|
// ── TTS (Text-to-Speech) ─────────────────────────────────────────────────────
|
|
30
31
|
export { ElevenLabsAdapter, ELEVENLABS_KOREAN_VOICES } from './tts/elevenlabs.js';
|
|
@@ -33,7 +34,7 @@ export { CachedTtsAdapter } from './tts/cached-tts.js';
|
|
|
33
34
|
export { GeminiTtsAdapter, GEMINI_TTS_VOICES } from './tts/gemini-tts.js';
|
|
34
35
|
export { CosyVoiceAdapter, COSYVOICE_VOICES } from './tts/cosyvoice-tts.js';
|
|
35
36
|
// ── LLM (Language Model) ─────────────────────────────────────────────────────
|
|
36
|
-
export { AnthropicAdapter } from './llm/anthropic.js';
|
|
37
|
+
export { AnthropicAdapter, acceptsSamplingParams } from './llm/anthropic.js';
|
|
37
38
|
export { OpenAILlmAdapter } from './llm/openai-llm.js';
|
|
38
39
|
export { WebhookAdapter } from './llm/webhook.js';
|
|
39
40
|
// ── Realtime Speech-to-Speech ─────────────────────────────────────────────────
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAmB,mBAAmB,CAAC;AAGjE,OAAO,EAAE,mBAAmB,EAAE,MAAe,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAmB,mBAAmB,CAAC;AAGjE,OAAO,EAAE,mBAAmB,EAAE,MAAe,wBAAwB,CAAC;AAGtE,OAAO,EAAE,cAAc,EAAE,MAAoB,eAAe,CAAC;AAS7D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,GACxB,MAA4C,eAAe,CAAC;AAE7D,gFAAgF;AAChF,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAGlF,OAAO,EAAE,gBAAgB,EAAE,MAAsB,qBAAqB,CAAC;AAOvE,OAAO,EAAE,gBAAgB,EAAE,MAAsB,qBAAqB,CAAC;AAMvE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAO1E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAO5E,gFAAgF;AAChF,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,gBAAgB,EAAE,MAAsB,qBAAqB,CAAC;AAGvE,OAAO,EAAE,cAAc,EAAE,MAAwB,kBAAkB,CAAC;AAGpE,iFAAiF;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAiB,+BAA+B,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/llm/anthropic.d.ts
CHANGED
|
@@ -4,19 +4,21 @@
|
|
|
4
4
|
* Integrates with the Anthropic Messages API for streaming LLM responses.
|
|
5
5
|
* Implements the LlmAdapter interface — returns streaming tokens as AsyncIterable.
|
|
6
6
|
*
|
|
7
|
-
* Model Reference
|
|
8
|
-
* claude-opus-4-6 — Most capable
|
|
9
|
-
* claude-sonnet-4-6 —
|
|
10
|
-
* claude-haiku-
|
|
7
|
+
* Model Reference:
|
|
8
|
+
* claude-opus-4-6 — Most capable of the 4.6 generation
|
|
9
|
+
* claude-sonnet-4-6 — Balance of speed and quality (default of this adapter)
|
|
10
|
+
* claude-haiku-5-5 — Fastest, lowest cost (best latency for voice bots)
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* Sampling parameters (SDK 1.9.12+):
|
|
13
|
+
* Claude Haiku 5.5, Sonnet 5.x, Opus 4.7 and later, and Fable reject a non-default
|
|
14
|
+
* `temperature` / `top_p` with HTTP 400. For those models this adapter sends neither
|
|
15
|
+
* (see `acceptsSamplingParams`) and warns once if you set one. Claude 4.x models that
|
|
16
|
+
* still accept sampling reject `temperature` and `top_p` together, so when `topP` is
|
|
17
|
+
* set the default temperature is not sent.
|
|
18
|
+
* ⚠️ Claude Haiku 5.5 thinks by default and its thinking tokens count toward
|
|
19
|
+
* `maxTokens`; only text deltas are yielded.
|
|
16
20
|
*
|
|
17
|
-
*
|
|
18
|
-
* claude-sonnet-4-6 and claude-opus-4-6 support extended thinking (budget_tokens).
|
|
19
|
-
* Not recommended for real-time voice (adds significant latency).
|
|
21
|
+
* Latency figures are not measured by this project — benchmark on your own traffic.
|
|
20
22
|
*
|
|
21
23
|
* Uses the official @anthropic-ai/sdk for correct streaming and error handling.
|
|
22
24
|
*
|
|
@@ -29,10 +31,10 @@ export interface AnthropicAdapterOptions {
|
|
|
29
31
|
/**
|
|
30
32
|
* Model ID (default: "claude-sonnet-4-6" — best voice balance)
|
|
31
33
|
*
|
|
32
|
-
*
|
|
33
|
-
* claude-opus-4-6
|
|
34
|
-
* claude-sonnet-4-6
|
|
35
|
-
* claude-haiku-
|
|
34
|
+
* Examples:
|
|
35
|
+
* claude-opus-4-6 — Most capable of the 4.6 generation (complex reasoning)
|
|
36
|
+
* claude-sonnet-4-6 — Balanced speed/quality (adapter default)
|
|
37
|
+
* claude-haiku-5-5 — Fastest (lowest latency, cost-effective)
|
|
36
38
|
*/
|
|
37
39
|
model?: string;
|
|
38
40
|
/** System prompt injected as the first message */
|
|
@@ -64,9 +66,24 @@ export interface AnthropicAdapterOptions {
|
|
|
64
66
|
*/
|
|
65
67
|
baseUrl?: string;
|
|
66
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Whether a model accepts `temperature` / `top_p`.
|
|
71
|
+
*
|
|
72
|
+
* Claude Haiku 5.5, Sonnet 5.x, Opus 4.7 and later, Fable and Mythos return HTTP 400 for
|
|
73
|
+
* non-default sampling values. Only the Claude generations known to accept them return
|
|
74
|
+
* true (3.x, 4.0/4.1, 4.5, 4.6); any other `claude-*` ID — including future ones — returns
|
|
75
|
+
* false, because sending a rejected parameter fails every request while omitting it only
|
|
76
|
+
* falls back to the model's default sampling. Non-Claude IDs (e.g. a local model behind an
|
|
77
|
+
* Anthropic-compatible `baseUrl`) return true so their requests stay as before.
|
|
78
|
+
*
|
|
79
|
+
* @since SDK 1.9.12
|
|
80
|
+
*/
|
|
81
|
+
export declare function acceptsSamplingParams(model: string): boolean;
|
|
67
82
|
export declare class AnthropicAdapter implements LlmAdapter {
|
|
68
83
|
private readonly client;
|
|
69
84
|
private readonly opts;
|
|
85
|
+
private readonly temperatureExplicit;
|
|
86
|
+
private readonly samplingWarned;
|
|
70
87
|
readonly systemPrompt: string;
|
|
71
88
|
constructor(opts: AnthropicAdapterOptions);
|
|
72
89
|
chat(messages: Message[], opts?: LlmOptions): AsyncIterable<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAErE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAID,qBAAa,gBAAiB,YAAW,UAAU;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IAGpD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAElB,IAAI,EAAE,uBAAuB;IAyBlC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;CAuD3E"}
|
package/dist/llm/anthropic.js
CHANGED
|
@@ -4,19 +4,21 @@
|
|
|
4
4
|
* Integrates with the Anthropic Messages API for streaming LLM responses.
|
|
5
5
|
* Implements the LlmAdapter interface — returns streaming tokens as AsyncIterable.
|
|
6
6
|
*
|
|
7
|
-
* Model Reference
|
|
8
|
-
* claude-opus-4-6 — Most capable
|
|
9
|
-
* claude-sonnet-4-6 —
|
|
10
|
-
* claude-haiku-
|
|
7
|
+
* Model Reference:
|
|
8
|
+
* claude-opus-4-6 — Most capable of the 4.6 generation
|
|
9
|
+
* claude-sonnet-4-6 — Balance of speed and quality (default of this adapter)
|
|
10
|
+
* claude-haiku-5-5 — Fastest, lowest cost (best latency for voice bots)
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* Sampling parameters (SDK 1.9.12+):
|
|
13
|
+
* Claude Haiku 5.5, Sonnet 5.x, Opus 4.7 and later, and Fable reject a non-default
|
|
14
|
+
* `temperature` / `top_p` with HTTP 400. For those models this adapter sends neither
|
|
15
|
+
* (see `acceptsSamplingParams`) and warns once if you set one. Claude 4.x models that
|
|
16
|
+
* still accept sampling reject `temperature` and `top_p` together, so when `topP` is
|
|
17
|
+
* set the default temperature is not sent.
|
|
18
|
+
* ⚠️ Claude Haiku 5.5 thinks by default and its thinking tokens count toward
|
|
19
|
+
* `maxTokens`; only text deltas are yielded.
|
|
16
20
|
*
|
|
17
|
-
*
|
|
18
|
-
* claude-sonnet-4-6 and claude-opus-4-6 support extended thinking (budget_tokens).
|
|
19
|
-
* Not recommended for real-time voice (adds significant latency).
|
|
21
|
+
* Latency figures are not measured by this project — benchmark on your own traffic.
|
|
20
22
|
*
|
|
21
23
|
* Uses the official @anthropic-ai/sdk for correct streaming and error handling.
|
|
22
24
|
*
|
|
@@ -24,9 +26,32 @@
|
|
|
24
26
|
* SDK: https://github.com/anthropics/anthropic-sdk-node
|
|
25
27
|
*/
|
|
26
28
|
import Anthropic from '@anthropic-ai/sdk';
|
|
29
|
+
/**
|
|
30
|
+
* Whether a model accepts `temperature` / `top_p`.
|
|
31
|
+
*
|
|
32
|
+
* Claude Haiku 5.5, Sonnet 5.x, Opus 4.7 and later, Fable and Mythos return HTTP 400 for
|
|
33
|
+
* non-default sampling values. Only the Claude generations known to accept them return
|
|
34
|
+
* true (3.x, 4.0/4.1, 4.5, 4.6); any other `claude-*` ID — including future ones — returns
|
|
35
|
+
* false, because sending a rejected parameter fails every request while omitting it only
|
|
36
|
+
* falls back to the model's default sampling. Non-Claude IDs (e.g. a local model behind an
|
|
37
|
+
* Anthropic-compatible `baseUrl`) return true so their requests stay as before.
|
|
38
|
+
*
|
|
39
|
+
* @since SDK 1.9.12
|
|
40
|
+
*/
|
|
41
|
+
export function acceptsSamplingParams(model) {
|
|
42
|
+
const m = model.trim().toLowerCase();
|
|
43
|
+
if (!m.startsWith('claude-'))
|
|
44
|
+
return true;
|
|
45
|
+
return (/^claude-(?:3|instant)/.test(m) ||
|
|
46
|
+
/^claude-(?:opus|sonnet|haiku)-4-(?:0|1|5|6)(?:$|[-@])/.test(m) ||
|
|
47
|
+
/^claude-(?:opus|sonnet)-4-\d{8}(?:$|[-@])/.test(m));
|
|
48
|
+
}
|
|
49
|
+
const DEFAULT_TEMPERATURE = 0.7;
|
|
27
50
|
export class AnthropicAdapter {
|
|
28
51
|
client;
|
|
29
52
|
opts;
|
|
53
|
+
temperatureExplicit;
|
|
54
|
+
samplingWarned = new Set();
|
|
30
55
|
// Expose systemPrompt for pipeline builder to read
|
|
31
56
|
systemPrompt;
|
|
32
57
|
constructor(opts) {
|
|
@@ -34,13 +59,14 @@ export class AnthropicAdapter {
|
|
|
34
59
|
model: opts.model ?? 'claude-sonnet-4-6',
|
|
35
60
|
systemPrompt: opts.systemPrompt ?? 'You are a helpful voice assistant. Keep answers concise and conversational, suitable for text-to-speech.',
|
|
36
61
|
maxTokens: opts.maxTokens ?? 1024,
|
|
37
|
-
temperature: opts.temperature ??
|
|
62
|
+
temperature: opts.temperature ?? DEFAULT_TEMPERATURE,
|
|
38
63
|
topP: opts.topP ?? undefined,
|
|
39
64
|
stopSequences: opts.stopSequences ?? [],
|
|
40
65
|
baseUrl: opts.baseUrl ?? '',
|
|
41
66
|
apiKey: opts.apiKey,
|
|
42
67
|
};
|
|
43
68
|
this.systemPrompt = this.opts.systemPrompt;
|
|
69
|
+
this.temperatureExplicit = opts.temperature !== undefined;
|
|
44
70
|
this.client = new Anthropic({
|
|
45
71
|
apiKey: opts.apiKey,
|
|
46
72
|
// baseUrl 이 비면 키 자체를 넘기지 않는다(공식 엔드포인트 유지).
|
|
@@ -53,8 +79,24 @@ export class AnthropicAdapter {
|
|
|
53
79
|
async *chat(messages, opts) {
|
|
54
80
|
const model = opts?.model ?? this.opts.model;
|
|
55
81
|
const maxTokens = opts?.maxTokens ?? this.opts.maxTokens;
|
|
56
|
-
const temperature = opts?.temperature ?? this.opts.temperature;
|
|
57
82
|
const systemPrompt = opts?.systemPrompt ?? this.opts.systemPrompt;
|
|
83
|
+
// Sampling: see acceptsSamplingParams. A value the caller set explicitly is dropped
|
|
84
|
+
// only with a warning (once per model) so the change is visible.
|
|
85
|
+
const temperatureExplicit = opts?.temperature !== undefined || this.temperatureExplicit;
|
|
86
|
+
let temperature = opts?.temperature ?? this.opts.temperature;
|
|
87
|
+
let topP = this.opts.topP;
|
|
88
|
+
if (!acceptsSamplingParams(model)) {
|
|
89
|
+
if ((temperatureExplicit || topP !== undefined) && !this.samplingWarned.has(model)) {
|
|
90
|
+
this.samplingWarned.add(model);
|
|
91
|
+
console.warn(`[AnthropicAdapter] ${model} rejects temperature/top_p — not sending them`);
|
|
92
|
+
}
|
|
93
|
+
temperature = undefined;
|
|
94
|
+
topP = undefined;
|
|
95
|
+
}
|
|
96
|
+
else if (topP !== undefined && !temperatureExplicit) {
|
|
97
|
+
// Claude 4.x rejects temperature and top_p together — send only the one the caller chose.
|
|
98
|
+
temperature = undefined;
|
|
99
|
+
}
|
|
58
100
|
// Separate system messages from conversation
|
|
59
101
|
const userMessages = messages.filter((m) => m.role !== 'system');
|
|
60
102
|
const systemContent = messages.find((m) => m.role === 'system')?.content ?? systemPrompt;
|
|
@@ -70,7 +112,7 @@ export class AnthropicAdapter {
|
|
|
70
112
|
system: systemContent,
|
|
71
113
|
messages: anthropicMessages,
|
|
72
114
|
...(temperature !== undefined && { temperature }),
|
|
73
|
-
...(
|
|
115
|
+
...(topP !== undefined && { top_p: topP }),
|
|
74
116
|
...(this.opts.stopSequences.length > 0 && { stop_sequences: this.opts.stopSequences }),
|
|
75
117
|
};
|
|
76
118
|
// Use streaming API — yields tokens as they arrive (low TTFT)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AnthropicAdapter } from './anthropic.js';
|
|
1
|
+
export { AnthropicAdapter, acceptsSamplingParams } from './anthropic.js';
|
|
2
2
|
export type { AnthropicAdapterOptions } from './anthropic.js';
|
|
3
3
|
export { OpenAILlmAdapter } from './openai-llm.js';
|
|
4
4
|
export type { OpenAILlmAdapterOptions } from './openai-llm.js';
|
package/dist/llm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACzE,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/llm/index.js
CHANGED
package/dist/llm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/llm/openai-llm.d.ts
CHANGED
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
* o3-mini — Reasoning model; not recommended for real-time voice (high latency)
|
|
12
12
|
* o1-mini — Reasoning model; not recommended for real-time voice (high latency)
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* gpt-4o — ~150ms TTFT
|
|
14
|
+
* For real-time voice, gpt-4o-mini is the usual choice. Latency (time to first token)
|
|
15
|
+
* is not measured by this project — benchmark on your own traffic.
|
|
17
16
|
*
|
|
18
17
|
* API Reference: https://platform.openai.com/docs/api-reference/chat
|
|
19
18
|
* SDK: https://github.com/openai/openai-node
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-llm.d.ts","sourceRoot":"","sources":["../../src/llm/openai-llm.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"openai-llm.d.ts","sourceRoot":"","sources":["../../src/llm/openai-llm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAErE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,gBAAiB,YAAW,UAAU;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IAEzD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAElB,IAAI,EAAE,uBAAuB;IAoBlC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;CA8B3E"}
|
package/dist/llm/openai-llm.js
CHANGED
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
* o3-mini — Reasoning model; not recommended for real-time voice (high latency)
|
|
12
12
|
* o1-mini — Reasoning model; not recommended for real-time voice (high latency)
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* gpt-4o — ~150ms TTFT
|
|
14
|
+
* For real-time voice, gpt-4o-mini is the usual choice. Latency (time to first token)
|
|
15
|
+
* is not measured by this project — benchmark on your own traffic.
|
|
17
16
|
*
|
|
18
17
|
* API Reference: https://platform.openai.com/docs/api-reference/chat
|
|
19
18
|
* SDK: https://github.com/openai/openai-node
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-llm.js","sourceRoot":"","sources":["../../src/llm/openai-llm.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"openai-llm.js","sourceRoot":"","sources":["../../src/llm/openai-llm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAyC5B,MAAM,OAAO,gBAAgB;IACV,MAAM,CAAS;IACf,IAAI,CAAoC;IAEhD,YAAY,CAAS;IAE9B,YAAY,IAA6B;QACvC,IAAI,CAAC,IAAI,GAAG;YACV,KAAK,EAAc,IAAI,CAAC,KAAK,IAAgB,aAAa;YAC1D,YAAY,EAAO,IAAI,CAAC,YAAY,IAAS,6EAA6E;YAC1H,SAAS,EAAU,IAAI,CAAC,SAAS,IAAY,IAAI;YACjD,WAAW,EAAQ,IAAI,CAAC,WAAW,IAAU,GAAG;YAChD,eAAe,EAAI,IAAI,CAAC,eAAe,IAAM,GAAG;YAChD,gBAAgB,EAAG,IAAI,CAAC,gBAAgB,IAAK,GAAG;YAChD,OAAO,EAAY,IAAI,CAAC,OAAO,IAAc,EAAE;YAC/C,MAAM,EAAa,IAAI,CAAC,MAAM;SAC/B,CAAC;QAEF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QAC3C,2CAA2C;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,CAAC,IAAI,CAAC,QAAmB,EAAE,IAAiB;QAChD,MAAM,KAAK,GAAS,IAAI,EAAE,KAAK,IAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QACzD,MAAM,SAAS,GAAK,IAAI,EAAE,SAAS,IAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QAC7D,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;QAC/D,MAAM,MAAM,GAAQ,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,OAAO;eACjE,IAAI,EAAE,YAAY;eAClB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QAE5B,MAAM,YAAY,GAA6C;YAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;YACnC,GAAG,QAAQ;iBACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;iBAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAA4B,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;SAC9E,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACvD,KAAK;YACL,UAAU,EAAS,SAAS;YAC5B,WAAW;YACX,gBAAgB,EAAG,IAAI,CAAC,IAAI,CAAC,eAAe;YAC5C,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAC7C,QAAQ,EAAW,YAAY;YAC/B,MAAM,EAAa,IAAI;SACxB,CAAC,CAAC;QAEH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC;YAC/C,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampling.test.d.ts","sourceRoot":"","sources":["../../src/llm/sampling.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sampling parameters sent by AnthropicAdapter (SDK 1.9.12).
|
|
3
|
+
*
|
|
4
|
+
* Claude Haiku 5.5, Sonnet 5.x, Opus 4.7+ and Fable return HTTP 400 for a non-default
|
|
5
|
+
* temperature/top_p, and the adapter used to send temperature 0.7 on every request —
|
|
6
|
+
* so pointing it at claude-haiku-5-5 failed every call. Claude 4.x also rejects
|
|
7
|
+
* temperature and top_p together. No network: the vendor client is replaced by a stub
|
|
8
|
+
* that records the request params.
|
|
9
|
+
*/
|
|
10
|
+
import { AnthropicAdapter, acceptsSamplingParams } from './anthropic.js';
|
|
11
|
+
// Same table as packages/dvgateway-python/tests/unit/test_anthropic_sampling.py — keep in sync.
|
|
12
|
+
const ACCEPTS = [
|
|
13
|
+
['claude-sonnet-4-6', true],
|
|
14
|
+
['claude-opus-4-6', true],
|
|
15
|
+
['claude-haiku-4-5', true],
|
|
16
|
+
['claude-haiku-4-5-20251001', true],
|
|
17
|
+
['claude-sonnet-4-5-20250929', true],
|
|
18
|
+
['claude-opus-4-1', true],
|
|
19
|
+
['claude-sonnet-4-20250514', true],
|
|
20
|
+
['claude-3-5-haiku-20241022', true],
|
|
21
|
+
['claude-haiku-5-5', false],
|
|
22
|
+
['claude-sonnet-5-5', false],
|
|
23
|
+
['claude-sonnet-5', false],
|
|
24
|
+
['claude-opus-5-5', false],
|
|
25
|
+
['claude-opus-4-7', false],
|
|
26
|
+
['claude-opus-4-8', false],
|
|
27
|
+
['claude-fable-5-1', false],
|
|
28
|
+
['claude-opus-4-10', false], // a future 4.x must not match the "4-1" family
|
|
29
|
+
['llama-3-local', true], // non-Claude model behind a compatible baseUrl: unchanged
|
|
30
|
+
];
|
|
31
|
+
function stubbed(adapter, events) {
|
|
32
|
+
const seen = [];
|
|
33
|
+
adapter.client = {
|
|
34
|
+
messages: {
|
|
35
|
+
stream(params) {
|
|
36
|
+
seen.push(params);
|
|
37
|
+
return (async function* () {
|
|
38
|
+
for (const e of events)
|
|
39
|
+
yield e;
|
|
40
|
+
})();
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
return seen;
|
|
45
|
+
}
|
|
46
|
+
const TEXT = [
|
|
47
|
+
{ type: 'content_block_delta', delta: { type: 'thinking_delta', thinking: '' } },
|
|
48
|
+
{ type: 'content_block_delta', delta: { type: 'text_delta', text: '안녕하세요' } },
|
|
49
|
+
];
|
|
50
|
+
async function collect(it) {
|
|
51
|
+
let s = '';
|
|
52
|
+
for await (const t of it)
|
|
53
|
+
s += t;
|
|
54
|
+
return s;
|
|
55
|
+
}
|
|
56
|
+
describe('acceptsSamplingParams', () => {
|
|
57
|
+
it.each(ACCEPTS)('%s → %s', (model, want) => {
|
|
58
|
+
expect(acceptsSamplingParams(model)).toBe(want);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('AnthropicAdapter sampling params', () => {
|
|
62
|
+
let warn;
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
warn = jest.spyOn(console, 'warn').mockImplementation(() => undefined);
|
|
65
|
+
});
|
|
66
|
+
afterEach(() => warn.mockRestore());
|
|
67
|
+
it('claude-haiku-5-5: no temperature/top_p, no warning when nothing was set, text only', async () => {
|
|
68
|
+
const a = new AnthropicAdapter({ apiKey: 'k', model: 'claude-haiku-5-5' });
|
|
69
|
+
const seen = stubbed(a, TEXT);
|
|
70
|
+
expect(await collect(a.chat([{ role: 'user', content: 'hi' }]))).toBe('안녕하세요');
|
|
71
|
+
expect(seen[0]).not.toHaveProperty('temperature');
|
|
72
|
+
expect(seen[0]).not.toHaveProperty('top_p');
|
|
73
|
+
expect(warn).not.toHaveBeenCalled();
|
|
74
|
+
});
|
|
75
|
+
it('explicit temperature on a rejecting model is dropped with one warning per model', async () => {
|
|
76
|
+
const a = new AnthropicAdapter({ apiKey: 'k', model: 'claude-haiku-5-5', temperature: 0.2 });
|
|
77
|
+
const seen = stubbed(a, TEXT);
|
|
78
|
+
await collect(a.chat([{ role: 'user', content: 'a' }]));
|
|
79
|
+
await collect(a.chat([{ role: 'user', content: 'b' }]));
|
|
80
|
+
expect(seen.every((p) => !('temperature' in p))).toBe(true);
|
|
81
|
+
expect(warn).toHaveBeenCalledTimes(1);
|
|
82
|
+
});
|
|
83
|
+
it('per-call model override is judged per call', async () => {
|
|
84
|
+
const a = new AnthropicAdapter({ apiKey: 'k' }); // default claude-sonnet-4-6
|
|
85
|
+
const seen = stubbed(a, TEXT);
|
|
86
|
+
await collect(a.chat([{ role: 'user', content: 'a' }]));
|
|
87
|
+
await collect(a.chat([{ role: 'user', content: 'b' }], { model: 'claude-opus-5-5' }));
|
|
88
|
+
expect(seen[0]?.temperature).toBe(0.7);
|
|
89
|
+
expect(seen[1]).not.toHaveProperty('temperature');
|
|
90
|
+
});
|
|
91
|
+
it('legacy model keeps the default temperature (unchanged behaviour)', async () => {
|
|
92
|
+
const a = new AnthropicAdapter({ apiKey: 'k', model: 'claude-haiku-4-5-20251001' });
|
|
93
|
+
const seen = stubbed(a, TEXT);
|
|
94
|
+
await collect(a.chat([{ role: 'user', content: 'a' }]));
|
|
95
|
+
expect(seen[0]?.temperature).toBe(0.7);
|
|
96
|
+
expect(seen[0]).not.toHaveProperty('top_p');
|
|
97
|
+
});
|
|
98
|
+
it('topP alone: default temperature is not sent with it (Claude 4.x rejects both)', async () => {
|
|
99
|
+
const a = new AnthropicAdapter({ apiKey: 'k', topP: 0.9 });
|
|
100
|
+
const seen = stubbed(a, TEXT);
|
|
101
|
+
await collect(a.chat([{ role: 'user', content: 'a' }]));
|
|
102
|
+
expect(seen[0]?.top_p).toBe(0.9);
|
|
103
|
+
expect(seen[0]).not.toHaveProperty('temperature');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=sampling.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampling.test.js","sourceRoot":"","sources":["../../src/llm/sampling.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,gGAAgG;AAChG,MAAM,OAAO,GAA6B;IACxC,CAAC,mBAAmB,EAAE,IAAI,CAAC;IAC3B,CAAC,iBAAiB,EAAE,IAAI,CAAC;IACzB,CAAC,kBAAkB,EAAE,IAAI,CAAC;IAC1B,CAAC,2BAA2B,EAAE,IAAI,CAAC;IACnC,CAAC,4BAA4B,EAAE,IAAI,CAAC;IACpC,CAAC,iBAAiB,EAAE,IAAI,CAAC;IACzB,CAAC,0BAA0B,EAAE,IAAI,CAAC;IAClC,CAAC,2BAA2B,EAAE,IAAI,CAAC;IACnC,CAAC,kBAAkB,EAAE,KAAK,CAAC;IAC3B,CAAC,mBAAmB,EAAE,KAAK,CAAC;IAC5B,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC1B,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC1B,CAAC,kBAAkB,EAAE,KAAK,CAAC;IAC3B,CAAC,kBAAkB,EAAE,KAAK,CAAC,EAAE,+CAA+C;IAC5E,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,0DAA0D;CACpF,CAAC;AAIF,SAAS,OAAO,CAAC,OAAyB,EAAE,MAAiB;IAC3D,MAAM,IAAI,GAAa,EAAE,CAAC;IACzB,OAA0C,CAAC,MAAM,GAAG;QACnD,QAAQ,EAAE;YACR,MAAM,CAAC,MAAc;gBACnB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClB,OAAO,CAAC,KAAK,SAAS,CAAC;oBACrB,KAAK,MAAM,CAAC,IAAI,MAAM;wBAAE,MAAM,CAAC,CAAC;gBAClC,CAAC,CAAC,EAAE,CAAC;YACP,CAAC;SACF;KACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,IAAI,GAAG;IACX,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE;IAChF,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;CAC9E,CAAC;AAEF,KAAK,UAAU,OAAO,CAAC,EAAyB;IAC9C,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE;QAAE,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC;AACX,CAAC;AAED,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC1C,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,IAAI,IAAsB,CAAC;IAC3B,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAEpC,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7F,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,4BAA4B;QAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;QACtF,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Implements a direct speech-to-speech pipeline using the OpenAI Realtime API.
|
|
5
5
|
* This adapter bypasses the traditional STT → LLM → TTS chain entirely —
|
|
6
|
-
* audio goes in, audio comes out
|
|
6
|
+
* audio goes in, audio comes out over one connection (latency not measured by this project).
|
|
7
7
|
*
|
|
8
8
|
* Architecture:
|
|
9
9
|
*
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* TTS injector → call audio
|
|
17
17
|
*
|
|
18
18
|
* Features:
|
|
19
|
-
* -
|
|
19
|
+
* - One connection instead of separate STT / LLM / TTS round trips
|
|
20
20
|
* - No separate STT/LLM/TTS billing — single API call
|
|
21
21
|
* - Native voice activity detection (server-side VAD)
|
|
22
22
|
* - Automatic conversation history management
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Implements a direct speech-to-speech pipeline using the OpenAI Realtime API.
|
|
5
5
|
* This adapter bypasses the traditional STT → LLM → TTS chain entirely —
|
|
6
|
-
* audio goes in, audio comes out
|
|
6
|
+
* audio goes in, audio comes out over one connection (latency not measured by this project).
|
|
7
7
|
*
|
|
8
8
|
* Architecture:
|
|
9
9
|
*
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* TTS injector → call audio
|
|
17
17
|
*
|
|
18
18
|
* Features:
|
|
19
|
-
* -
|
|
19
|
+
* - One connection instead of separate STT / LLM / TTS round trips
|
|
20
20
|
* - No separate STT/LLM/TTS billing — single API call
|
|
21
21
|
* - Native voice activity detection (server-side VAD)
|
|
22
22
|
* - Automatic conversation history management
|
package/dist/stt/index.d.ts
CHANGED
|
@@ -4,4 +4,6 @@ export { GoogleChirp3Adapter } from './google-chirp3.js';
|
|
|
4
4
|
export type { GoogleChirp3AdapterOptions } from './google-chirp3.js';
|
|
5
5
|
export { OpenAISttAdapter } from './openai-stt.js';
|
|
6
6
|
export type { OpenAISttAdapterOptions } from './openai-stt.js';
|
|
7
|
+
export { RtzrSttAdapter, rtzrKeywords } from './rtzr.js';
|
|
8
|
+
export type { RtzrSttAdapterOptions } from './rtzr.js';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/stt/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stt/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stt/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/stt/index.js
CHANGED
package/dist/stt/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stt/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stt/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReturnZero (RTZR) STT Adapter — Korean telephony streaming STT.
|
|
3
|
+
*
|
|
4
|
+
* Streams 16kHz slin16 PCM to RTZR's WebSocket API and fires onTranscript for
|
|
5
|
+
* partial (isFinal=false) and final (isFinal=true) results.
|
|
6
|
+
*
|
|
7
|
+
* Why: in our 2026-10-14 comparison (synthetic phone audio, AWS Seoul) RTZR
|
|
8
|
+
* caught more Korean addresses and phone numbers than Deepgram Nova-3 and
|
|
9
|
+
* connected in ~14ms from Korea; its final result arrived ~90ms later because
|
|
10
|
+
* the server waits for its own end-of-speech (EPD). Call `finalize()` at your
|
|
11
|
+
* own end-of-turn to get the final result immediately (RTZR blog: p50
|
|
12
|
+
* 702ms → 24ms).
|
|
13
|
+
*
|
|
14
|
+
* Protocol (developers.rtzr.ai, checked 2026-10-14):
|
|
15
|
+
* POST https://openapi.vito.ai/v1/authenticate (form: client_id, client_secret)
|
|
16
|
+
* → { access_token } — valid 6 hours
|
|
17
|
+
* wss://openapi.vito.ai/v1/transcribe:streaming?sample_rate=16000&encoding=LINEAR16&…
|
|
18
|
+
* Authorization: Bearer <token>
|
|
19
|
+
* send: binary raw PCM · text {"type":"Finalize"} · text "EOS" (end of stream)
|
|
20
|
+
* recv: { seq, start_at, duration, final, alternatives: [{ text, confidence }] }
|
|
21
|
+
* The server drops a connection that sends no audio for 60s.
|
|
22
|
+
*
|
|
23
|
+
* Keywords: Hangul syllables and spaces only, ≤20 chars each, ≤100 words
|
|
24
|
+
* (sommers_ko only). Anything else makes the handshake fail (HTTP 400), so
|
|
25
|
+
* this adapter drops it and logs only the count.
|
|
26
|
+
*
|
|
27
|
+
* @since SDK 1.9.13
|
|
28
|
+
*/
|
|
29
|
+
import type { SttAdapter, AudioChunk, TranscriptResult } from 'dvgateway-sdk';
|
|
30
|
+
export interface RtzrSttAdapterOptions {
|
|
31
|
+
/** RTZR console client ID */
|
|
32
|
+
clientId: string;
|
|
33
|
+
/** RTZR console client secret */
|
|
34
|
+
clientSecret: string;
|
|
35
|
+
/** Language code (default: "ko"). "ja" → sommers_ja, others → whisper */
|
|
36
|
+
language?: string;
|
|
37
|
+
/** Model override (default: derived from language — sommers_ko) */
|
|
38
|
+
model?: string;
|
|
39
|
+
/** "CALL" (phone, default) or "MEETING" (far-field) */
|
|
40
|
+
domain?: 'CALL' | 'MEETING';
|
|
41
|
+
/** Inverse text normalization — "공일공" → "010" (default: true) */
|
|
42
|
+
useItn?: boolean;
|
|
43
|
+
/** Remove fillers like "음", "어" (default: false) */
|
|
44
|
+
useDisfluencyFilter?: boolean;
|
|
45
|
+
/** Mask profanity (default: false) */
|
|
46
|
+
useProfanityFilter?: boolean;
|
|
47
|
+
/** Add punctuation (default: false) */
|
|
48
|
+
usePunctuation?: boolean;
|
|
49
|
+
/** Keyword boosting: "word" or "word:score" (Hangul only) */
|
|
50
|
+
keywords?: string[];
|
|
51
|
+
/** Override API base (tests) */
|
|
52
|
+
authUrl?: string;
|
|
53
|
+
streamUrl?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Keep only keywords RTZR accepts (Hangul + spaces, optional ":score"). */
|
|
56
|
+
export declare function rtzrKeywords(terms: readonly string[]): {
|
|
57
|
+
kept: string[];
|
|
58
|
+
dropped: number;
|
|
59
|
+
};
|
|
60
|
+
export declare class RtzrSttAdapter implements SttAdapter {
|
|
61
|
+
private readonly opts;
|
|
62
|
+
private transcriptHandler;
|
|
63
|
+
private ws;
|
|
64
|
+
private stopped;
|
|
65
|
+
private linkedId;
|
|
66
|
+
constructor(opts: RtzrSttAdapterOptions);
|
|
67
|
+
onTranscript(handler: (result: TranscriptResult) => void): void;
|
|
68
|
+
startStream(linkedId: string, audioStream: AsyncIterable<AudioChunk>): Promise<void>;
|
|
69
|
+
/** Ask the server to finalize the current utterance now (connection stays open). */
|
|
70
|
+
finalize(): void;
|
|
71
|
+
stop(): Promise<void>;
|
|
72
|
+
/** Query string for the streaming endpoint (exported for tests). */
|
|
73
|
+
buildQuery(): URLSearchParams;
|
|
74
|
+
private token;
|
|
75
|
+
private connect;
|
|
76
|
+
private dial;
|
|
77
|
+
private pipeAudio;
|
|
78
|
+
private handleMessage;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=rtzr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtzr.d.ts","sourceRoot":"","sources":["../../src/stt/rtzr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAG9E,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAkB1F;AAID,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqE;IAC1F,OAAO,CAAC,iBAAiB,CAAqD;IAC9E,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAM;gBAEV,IAAI,EAAE,qBAAqB;IAuBvC,YAAY,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IAIzD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB1F,oFAAoF;IACpF,QAAQ,IAAI,IAAI;IAMV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,oEAAoE;IACpE,UAAU,IAAI,eAAe;YAsBf,KAAK;YAgBL,OAAO;IAerB,OAAO,CAAC,IAAI;YAaE,SAAS;IAOvB,OAAO,CAAC,aAAa;CAmBtB"}
|
package/dist/stt/rtzr.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReturnZero (RTZR) STT Adapter — Korean telephony streaming STT.
|
|
3
|
+
*
|
|
4
|
+
* Streams 16kHz slin16 PCM to RTZR's WebSocket API and fires onTranscript for
|
|
5
|
+
* partial (isFinal=false) and final (isFinal=true) results.
|
|
6
|
+
*
|
|
7
|
+
* Why: in our 2026-10-14 comparison (synthetic phone audio, AWS Seoul) RTZR
|
|
8
|
+
* caught more Korean addresses and phone numbers than Deepgram Nova-3 and
|
|
9
|
+
* connected in ~14ms from Korea; its final result arrived ~90ms later because
|
|
10
|
+
* the server waits for its own end-of-speech (EPD). Call `finalize()` at your
|
|
11
|
+
* own end-of-turn to get the final result immediately (RTZR blog: p50
|
|
12
|
+
* 702ms → 24ms).
|
|
13
|
+
*
|
|
14
|
+
* Protocol (developers.rtzr.ai, checked 2026-10-14):
|
|
15
|
+
* POST https://openapi.vito.ai/v1/authenticate (form: client_id, client_secret)
|
|
16
|
+
* → { access_token } — valid 6 hours
|
|
17
|
+
* wss://openapi.vito.ai/v1/transcribe:streaming?sample_rate=16000&encoding=LINEAR16&…
|
|
18
|
+
* Authorization: Bearer <token>
|
|
19
|
+
* send: binary raw PCM · text {"type":"Finalize"} · text "EOS" (end of stream)
|
|
20
|
+
* recv: { seq, start_at, duration, final, alternatives: [{ text, confidence }] }
|
|
21
|
+
* The server drops a connection that sends no audio for 60s.
|
|
22
|
+
*
|
|
23
|
+
* Keywords: Hangul syllables and spaces only, ≤20 chars each, ≤100 words
|
|
24
|
+
* (sommers_ko only). Anything else makes the handshake fail (HTTP 400), so
|
|
25
|
+
* this adapter drops it and logs only the count.
|
|
26
|
+
*
|
|
27
|
+
* @since SDK 1.9.13
|
|
28
|
+
*/
|
|
29
|
+
import WebSocket from 'ws';
|
|
30
|
+
import { float32ToSlin16 } from 'dvgateway-sdk';
|
|
31
|
+
const AUTH_URL = 'https://openapi.vito.ai/v1/authenticate';
|
|
32
|
+
const STREAM_URL = 'wss://openapi.vito.ai/v1/transcribe:streaming';
|
|
33
|
+
const TOKEN_REUSE_MS = 5 * 60 * 60 * 1000; // token lives 6h
|
|
34
|
+
const KEYWORD_MAX = 100;
|
|
35
|
+
const KEYWORD_MAX_LEN = 20;
|
|
36
|
+
/** Keep only keywords RTZR accepts (Hangul + spaces, optional ":score"). */
|
|
37
|
+
export function rtzrKeywords(terms) {
|
|
38
|
+
const kept = [];
|
|
39
|
+
const seen = new Set();
|
|
40
|
+
let dropped = 0;
|
|
41
|
+
for (const raw of terms) {
|
|
42
|
+
const t = raw.trim();
|
|
43
|
+
if (!t || seen.has(t))
|
|
44
|
+
continue;
|
|
45
|
+
const [word = '', score] = t.split(':', 2);
|
|
46
|
+
const wordOk = word.length > 0 && [...word].length <= KEYWORD_MAX_LEN && /^[가-힣 ]+$/.test(word);
|
|
47
|
+
const scoreOk = score === undefined || (/^-?\d+(\.\d+)?$/.test(score) && Math.abs(Number(score)) <= 5);
|
|
48
|
+
if (!wordOk || !scoreOk || kept.length >= KEYWORD_MAX) {
|
|
49
|
+
dropped++;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
seen.add(t);
|
|
53
|
+
kept.push(t);
|
|
54
|
+
}
|
|
55
|
+
return { kept, dropped };
|
|
56
|
+
}
|
|
57
|
+
const tokenCache = new Map();
|
|
58
|
+
export class RtzrSttAdapter {
|
|
59
|
+
opts;
|
|
60
|
+
transcriptHandler = null;
|
|
61
|
+
ws = null;
|
|
62
|
+
stopped = false;
|
|
63
|
+
linkedId = '';
|
|
64
|
+
constructor(opts) {
|
|
65
|
+
if (!opts.clientId || !opts.clientSecret) {
|
|
66
|
+
throw new Error('RtzrSttAdapter: clientId and clientSecret are required');
|
|
67
|
+
}
|
|
68
|
+
const language = opts.language ?? 'ko';
|
|
69
|
+
const model = opts.model
|
|
70
|
+
?? (language.startsWith('ja') ? 'sommers_ja' : language.startsWith('ko') ? 'sommers_ko' : 'whisper');
|
|
71
|
+
this.opts = {
|
|
72
|
+
clientId: opts.clientId,
|
|
73
|
+
clientSecret: opts.clientSecret,
|
|
74
|
+
language,
|
|
75
|
+
model,
|
|
76
|
+
domain: opts.domain ?? 'CALL',
|
|
77
|
+
useItn: opts.useItn ?? true,
|
|
78
|
+
useDisfluencyFilter: opts.useDisfluencyFilter ?? false,
|
|
79
|
+
useProfanityFilter: opts.useProfanityFilter ?? false,
|
|
80
|
+
usePunctuation: opts.usePunctuation ?? false,
|
|
81
|
+
keywords: opts.keywords ?? [],
|
|
82
|
+
authUrl: opts.authUrl ?? AUTH_URL,
|
|
83
|
+
streamUrl: opts.streamUrl ?? STREAM_URL,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
onTranscript(handler) {
|
|
87
|
+
this.transcriptHandler = handler;
|
|
88
|
+
}
|
|
89
|
+
async startStream(linkedId, audioStream) {
|
|
90
|
+
this.stopped = false;
|
|
91
|
+
this.linkedId = linkedId;
|
|
92
|
+
this.ws = await this.connect();
|
|
93
|
+
void this.pipeAudio(audioStream);
|
|
94
|
+
await new Promise((resolve) => {
|
|
95
|
+
this.ws?.once('close', () => resolve());
|
|
96
|
+
const t = setInterval(() => {
|
|
97
|
+
if (this.stopped) {
|
|
98
|
+
clearInterval(t);
|
|
99
|
+
resolve();
|
|
100
|
+
}
|
|
101
|
+
}, 100);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/** Ask the server to finalize the current utterance now (connection stays open). */
|
|
105
|
+
finalize() {
|
|
106
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
107
|
+
this.ws.send(JSON.stringify({ type: 'Finalize' }));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async stop() {
|
|
111
|
+
this.stopped = true;
|
|
112
|
+
const ws = this.ws;
|
|
113
|
+
this.ws = null;
|
|
114
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
115
|
+
ws.send('EOS');
|
|
116
|
+
setTimeout(() => ws.close(1000, 'stop'), 200);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Query string for the streaming endpoint (exported for tests). */
|
|
120
|
+
buildQuery() {
|
|
121
|
+
const q = new URLSearchParams({
|
|
122
|
+
sample_rate: '16000',
|
|
123
|
+
encoding: 'LINEAR16',
|
|
124
|
+
model_name: this.opts.model,
|
|
125
|
+
domain: this.opts.domain,
|
|
126
|
+
use_itn: String(this.opts.useItn),
|
|
127
|
+
use_disfluency_filter: String(this.opts.useDisfluencyFilter),
|
|
128
|
+
use_profanity_filter: String(this.opts.useProfanityFilter),
|
|
129
|
+
use_punctuation: String(this.opts.usePunctuation),
|
|
130
|
+
});
|
|
131
|
+
if (this.opts.model === 'whisper')
|
|
132
|
+
q.set('language', this.opts.language);
|
|
133
|
+
const { kept, dropped } = rtzrKeywords(this.opts.keywords);
|
|
134
|
+
if (dropped > 0) {
|
|
135
|
+
process.stderr.write(`[RtzrSttAdapter] ${dropped} keyword(s) dropped (Hangul only, ≤20 chars, ≤100)\n`);
|
|
136
|
+
}
|
|
137
|
+
if (kept.length > 0 && (this.opts.model === 'sommers_ko' || (this.opts.model === 'whisper' && this.opts.language.startsWith('ko')))) {
|
|
138
|
+
q.set('keywords', kept.join(','));
|
|
139
|
+
}
|
|
140
|
+
return q;
|
|
141
|
+
}
|
|
142
|
+
async token(fresh) {
|
|
143
|
+
const cached = tokenCache.get(this.opts.clientId);
|
|
144
|
+
if (cached && !fresh && Date.now() - cached.at < TOKEN_REUSE_MS)
|
|
145
|
+
return cached.token;
|
|
146
|
+
const res = await fetch(this.opts.authUrl, {
|
|
147
|
+
method: 'POST',
|
|
148
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
149
|
+
body: new URLSearchParams({ client_id: this.opts.clientId, client_secret: this.opts.clientSecret }).toString(),
|
|
150
|
+
});
|
|
151
|
+
const body = await res.text();
|
|
152
|
+
if (!res.ok)
|
|
153
|
+
throw new Error(`RTZR auth HTTP ${res.status}: ${body.slice(0, 120)}`);
|
|
154
|
+
const token = JSON.parse(body).access_token;
|
|
155
|
+
if (!token)
|
|
156
|
+
throw new Error('RTZR auth response has no access_token');
|
|
157
|
+
tokenCache.set(this.opts.clientId, { token, at: Date.now() });
|
|
158
|
+
return token;
|
|
159
|
+
}
|
|
160
|
+
async connect() {
|
|
161
|
+
const url = `${this.opts.streamUrl}?${this.buildQuery().toString()}`;
|
|
162
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
163
|
+
const token = await this.token(attempt > 0);
|
|
164
|
+
try {
|
|
165
|
+
return await this.dial(url, token);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
// 401 = token revoked/expired elsewhere — retry once with a fresh token.
|
|
169
|
+
if (attempt === 0 && err instanceof Error && err.message.includes('401'))
|
|
170
|
+
continue;
|
|
171
|
+
throw err;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
throw new Error('RTZR connect: unauthorized');
|
|
175
|
+
}
|
|
176
|
+
dial(url, token) {
|
|
177
|
+
return new Promise((resolve, reject) => {
|
|
178
|
+
const ws = new WebSocket(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
179
|
+
ws.once('unexpected-response', (_req, res) => reject(new Error(`RTZR connect HTTP ${res.statusCode}`)));
|
|
180
|
+
ws.once('error', reject);
|
|
181
|
+
ws.once('open', () => {
|
|
182
|
+
ws.on('message', (data) => this.handleMessage(data));
|
|
183
|
+
ws.on('error', (err) => process.stderr.write(`[RtzrSttAdapter] WebSocket error: ${err.message}\n`));
|
|
184
|
+
resolve(ws);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
async pipeAudio(audioStream) {
|
|
189
|
+
for await (const chunk of audioStream) {
|
|
190
|
+
if (this.stopped || !this.ws || this.ws.readyState !== WebSocket.OPEN)
|
|
191
|
+
break;
|
|
192
|
+
this.ws.send(float32ToSlin16(chunk.samples));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
handleMessage(data) {
|
|
196
|
+
let msg;
|
|
197
|
+
try {
|
|
198
|
+
msg = JSON.parse(data.toString());
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const alt = msg.alternatives?.[0];
|
|
204
|
+
const text = alt?.text?.trim();
|
|
205
|
+
if (!text)
|
|
206
|
+
return;
|
|
207
|
+
this.transcriptHandler?.({
|
|
208
|
+
linkedId: this.linkedId,
|
|
209
|
+
text,
|
|
210
|
+
isFinal: msg.final === true,
|
|
211
|
+
...(typeof alt?.confidence === 'number' ? { confidence: alt.confidence } : {}),
|
|
212
|
+
language: this.opts.language,
|
|
213
|
+
timestampMs: Date.now(),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=rtzr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtzr.js","sourceRoot":"","sources":["../../src/stt/rtzr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtzr.test.d.ts","sourceRoot":"","sources":["../../src/stt/rtzr.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RtzrSttAdapter — keyword rules, query building, and a full stream against
|
|
3
|
+
* local fake auth + WebSocket servers (no network).
|
|
4
|
+
*/
|
|
5
|
+
import http from 'http';
|
|
6
|
+
import { WebSocketServer } from 'ws';
|
|
7
|
+
import { RtzrSttAdapter, rtzrKeywords } from './rtzr.js';
|
|
8
|
+
describe('rtzrKeywords', () => {
|
|
9
|
+
it('keeps Hangul words (with optional score) and drops the rest', () => {
|
|
10
|
+
const { kept, dropped } = rtzrKeywords(['선불', '착불:3.5', '선불', 'STT', '1톤', '가'.repeat(21), '다마스:9']);
|
|
11
|
+
expect(kept).toEqual(['선불', '착불:3.5']);
|
|
12
|
+
expect(dropped).toBe(4);
|
|
13
|
+
});
|
|
14
|
+
it('caps at 100 words', () => {
|
|
15
|
+
const many = Array.from({ length: 120 }, (_, i) => String.fromCharCode(0xac00 + i));
|
|
16
|
+
expect(rtzrKeywords(many).kept).toHaveLength(100);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('RtzrSttAdapter.buildQuery', () => {
|
|
20
|
+
it('uses the Korean phone model with ITN and only valid keywords', () => {
|
|
21
|
+
const a = new RtzrSttAdapter({ clientId: 'i', clientSecret: 's', keywords: ['선불', 'STT'] });
|
|
22
|
+
const q = a.buildQuery();
|
|
23
|
+
expect(q.get('model_name')).toBe('sommers_ko');
|
|
24
|
+
expect(q.get('domain')).toBe('CALL');
|
|
25
|
+
expect(q.get('use_itn')).toBe('true');
|
|
26
|
+
expect(q.get('sample_rate')).toBe('16000');
|
|
27
|
+
expect(q.get('keywords')).toBe('선불');
|
|
28
|
+
});
|
|
29
|
+
it('does not send keywords to sommers_ja', () => {
|
|
30
|
+
const q = new RtzrSttAdapter({ clientId: 'i', clientSecret: 's', language: 'ja', keywords: ['선불'] }).buildQuery();
|
|
31
|
+
expect(q.get('model_name')).toBe('sommers_ja');
|
|
32
|
+
expect(q.get('keywords')).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
it('requires credentials', () => {
|
|
35
|
+
expect(() => new RtzrSttAdapter({ clientId: '', clientSecret: 's' })).toThrow();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
async function* oneSecondOfAudio() {
|
|
39
|
+
for (let i = 0; i < 5; i++) {
|
|
40
|
+
yield { linkedId: 'L1', dir: 'in', samples: new Float32Array(320), sampleRate: 16000, durationMs: 20, timestampMs: i * 20 };
|
|
41
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
describe('RtzrSttAdapter stream', () => {
|
|
45
|
+
it('authenticates, streams PCM, emits partial + final, and sends EOS on stop', async () => {
|
|
46
|
+
let auth = '';
|
|
47
|
+
let gotEOS = false;
|
|
48
|
+
let gotFinalize = false;
|
|
49
|
+
const authServer = http.createServer((req, res) => {
|
|
50
|
+
let body = '';
|
|
51
|
+
req.on('data', (c) => (body += c));
|
|
52
|
+
req.on('end', () => {
|
|
53
|
+
const p = new URLSearchParams(body);
|
|
54
|
+
res.end(JSON.stringify({ access_token: p.get('client_id') === 'cid' ? 'tok1' : '' }));
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
await new Promise((r) => authServer.listen(0, r));
|
|
58
|
+
const wss = new WebSocketServer({ port: 0 });
|
|
59
|
+
await new Promise((r) => wss.once('listening', () => r()));
|
|
60
|
+
wss.on('connection', (ws, req) => {
|
|
61
|
+
auth = req.headers.authorization ?? '';
|
|
62
|
+
let frames = 0;
|
|
63
|
+
ws.on('message', (data, isBinary) => {
|
|
64
|
+
if (!isBinary) {
|
|
65
|
+
const s = data.toString();
|
|
66
|
+
if (s === 'EOS')
|
|
67
|
+
gotEOS = true;
|
|
68
|
+
if (s.includes('Finalize'))
|
|
69
|
+
gotFinalize = true;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (++frames === 2) {
|
|
73
|
+
ws.send(JSON.stringify({ seq: 0, final: false, alternatives: [{ text: '선' }] }));
|
|
74
|
+
ws.send(JSON.stringify({ seq: 0, final: true, alternatives: [{ text: '선불', confidence: 0.9 }] }));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
const results = [];
|
|
79
|
+
const a = new RtzrSttAdapter({
|
|
80
|
+
clientId: 'cid',
|
|
81
|
+
clientSecret: 'sec',
|
|
82
|
+
authUrl: `http://127.0.0.1:${authServer.address().port}`,
|
|
83
|
+
streamUrl: `ws://127.0.0.1:${wss.address().port}`,
|
|
84
|
+
});
|
|
85
|
+
a.onTranscript((r) => results.push(r));
|
|
86
|
+
const done = a.startStream('L1', oneSecondOfAudio());
|
|
87
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
88
|
+
a.finalize();
|
|
89
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
90
|
+
await a.stop();
|
|
91
|
+
await done;
|
|
92
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
93
|
+
expect(auth).toBe('Bearer tok1');
|
|
94
|
+
expect(results.map((r) => [r.text, r.isFinal])).toEqual([['선', false], ['선불', true]]);
|
|
95
|
+
expect(results[1]?.linkedId).toBe('L1');
|
|
96
|
+
expect(gotFinalize).toBe(true);
|
|
97
|
+
expect(gotEOS).toBe(true);
|
|
98
|
+
wss.close();
|
|
99
|
+
authServer.close();
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=rtzr.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtzr.test.js","sourceRoot":"","sources":["../../src/stt/rtzr.test.ts"],"names":[],"mappings":"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"}
|
package/dist/tts/elevenlabs.d.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - Voice settings: stability, similarity boost, style, speed
|
|
13
13
|
*
|
|
14
14
|
* ElevenLabs Model Reference (2026-03):
|
|
15
|
-
* eleven_flash_v2_5 —
|
|
16
|
-
* eleven_turbo_v2_5 — Balanced quality/speed
|
|
15
|
+
* eleven_flash_v2_5 — Lowest latency per the vendor, best for real-time voice (default)
|
|
16
|
+
* eleven_turbo_v2_5 — Balanced quality/speed
|
|
17
17
|
* eleven_multilingual_v2 — Highest multilingual quality (higher latency)
|
|
18
18
|
* eleven_multilingual_v3 — Next-gen multilingual, improved prosody (2026)
|
|
19
19
|
* eleven_english_sts_v2 — English speech-to-speech transformation
|
|
@@ -35,7 +35,7 @@ export interface ElevenLabsAdapterOptions {
|
|
|
35
35
|
/**
|
|
36
36
|
* Model ID (default: "eleven_multilingual_v2" when humanVoice enabled, "eleven_flash_v2_5" otherwise)
|
|
37
37
|
* Options:
|
|
38
|
-
* eleven_flash_v2_5 —
|
|
38
|
+
* eleven_flash_v2_5 — Lowest latency per the vendor, best for real-time voice
|
|
39
39
|
* eleven_turbo_v2_5 — Balanced quality/speed
|
|
40
40
|
* eleven_multilingual_v2 — Best multilingual quality (higher latency)
|
|
41
41
|
* eleven_multilingual_v3 — Next-gen multilingual (2026, improved prosody)
|
package/dist/tts/elevenlabs.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - Voice settings: stability, similarity boost, style, speed
|
|
13
13
|
*
|
|
14
14
|
* ElevenLabs Model Reference (2026-03):
|
|
15
|
-
* eleven_flash_v2_5 —
|
|
16
|
-
* eleven_turbo_v2_5 — Balanced quality/speed
|
|
15
|
+
* eleven_flash_v2_5 — Lowest latency per the vendor, best for real-time voice (default)
|
|
16
|
+
* eleven_turbo_v2_5 — Balanced quality/speed
|
|
17
17
|
* eleven_multilingual_v2 — Highest multilingual quality (higher latency)
|
|
18
18
|
* eleven_multilingual_v3 — Next-gen multilingual, improved prosody (2026)
|
|
19
19
|
* eleven_english_sts_v2 — English speech-to-speech transformation
|
package/dist/tts/openai-tts.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Streams PCM audio chunks resampled to 16kHz for DVGateway injection.
|
|
6
6
|
*
|
|
7
7
|
* Model Reference (2026-03):
|
|
8
|
-
* tts-1 — Optimized for real-time speed (default
|
|
8
|
+
* tts-1 — Optimized for real-time speed (default)
|
|
9
9
|
* tts-1-hd — Optimized for quality (studio output, higher latency)
|
|
10
10
|
* gpt-4o-mini-tts — Latest neural TTS model; better prosody, emotions (2025+)
|
|
11
11
|
*
|
|
@@ -36,8 +36,8 @@ export interface OpenAITtsAdapterOptions {
|
|
|
36
36
|
voice?: OpenAITtsVoice;
|
|
37
37
|
/**
|
|
38
38
|
* Model (default: "gpt-4o-mini-tts" when humanVoice enabled, "tts-1" otherwise)
|
|
39
|
-
* tts-1 — Real-time optimized
|
|
40
|
-
* tts-1-hd — Quality optimized (
|
|
39
|
+
* tts-1 — Real-time optimized
|
|
40
|
+
* tts-1-hd — Quality optimized (higher latency)
|
|
41
41
|
* gpt-4o-mini-tts — Neural model, best prosody and emotion (2025+)
|
|
42
42
|
*/
|
|
43
43
|
model?: OpenAITtsModel;
|
package/dist/tts/openai-tts.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Streams PCM audio chunks resampled to 16kHz for DVGateway injection.
|
|
6
6
|
*
|
|
7
7
|
* Model Reference (2026-03):
|
|
8
|
-
* tts-1 — Optimized for real-time speed (default
|
|
8
|
+
* tts-1 — Optimized for real-time speed (default)
|
|
9
9
|
* tts-1-hd — Optimized for quality (studio output, higher latency)
|
|
10
10
|
* gpt-4o-mini-tts — Latest neural TTS model; better prosody, emotions (2025+)
|
|
11
11
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dvgateway-adapters",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.13",
|
|
4
4
|
"description": "AI service adapters for DVGateway SDK (Deepgram, ElevenLabs, Anthropic, OpenAI, OpenAI Realtime, OpenAI GPT-Live, Gemini Live)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
"keywords": [
|
|
43
43
|
"dvgateway",
|
|
44
44
|
"deepgram",
|
|
45
|
+
"rtzr",
|
|
46
|
+
"returnzero",
|
|
45
47
|
"elevenlabs",
|
|
46
48
|
"anthropic",
|
|
47
49
|
"openai",
|