@framers/agentos 0.1.227 → 0.1.229
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/api/editImage.d.ts +21 -0
- package/dist/api/editImage.d.ts.map +1 -1
- package/dist/api/editImage.js +30 -2
- package/dist/api/editImage.js.map +1 -1
- package/dist/api/generateImage.d.ts +12 -1
- package/dist/api/generateImage.d.ts.map +1 -1
- package/dist/api/generateImage.js +7 -2
- package/dist/api/generateImage.js.map +1 -1
- package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/AnthropicProvider.js +71 -12
- package/dist/core/llm/providers/implementations/AnthropicProvider.js.map +1 -1
- package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts.map +1 -1
- package/dist/core/llm/providers/implementations/OpenAIProvider.js +38 -11
- package/dist/core/llm/providers/implementations/OpenAIProvider.js.map +1 -1
- package/dist/media/images/providers/ReplicateImageProvider.d.ts.map +1 -1
- package/dist/media/images/providers/ReplicateImageProvider.js +7 -0
- package/dist/media/images/providers/ReplicateImageProvider.js.map +1 -1
- package/dist/voice-pipeline/AudioRingBuffer.d.ts +28 -0
- package/dist/voice-pipeline/AudioRingBuffer.d.ts.map +1 -0
- package/dist/voice-pipeline/AudioRingBuffer.js +43 -0
- package/dist/voice-pipeline/AudioRingBuffer.js.map +1 -0
- package/dist/voice-pipeline/CircuitBreaker.d.ts +42 -0
- package/dist/voice-pipeline/CircuitBreaker.d.ts.map +1 -0
- package/dist/voice-pipeline/CircuitBreaker.js +96 -0
- package/dist/voice-pipeline/CircuitBreaker.js.map +1 -0
- package/dist/voice-pipeline/HealthyProvider.d.ts +44 -0
- package/dist/voice-pipeline/HealthyProvider.d.ts.map +1 -0
- package/dist/voice-pipeline/HealthyProvider.js +29 -0
- package/dist/voice-pipeline/HealthyProvider.js.map +1 -0
- package/dist/voice-pipeline/TranscriptDedupe.d.ts +43 -0
- package/dist/voice-pipeline/TranscriptDedupe.d.ts.map +1 -0
- package/dist/voice-pipeline/TranscriptDedupe.js +96 -0
- package/dist/voice-pipeline/TranscriptDedupe.js.map +1 -0
- package/dist/voice-pipeline/VoiceMetricsReporter.d.ts +48 -0
- package/dist/voice-pipeline/VoiceMetricsReporter.d.ts.map +1 -0
- package/dist/voice-pipeline/VoiceMetricsReporter.js +33 -0
- package/dist/voice-pipeline/VoiceMetricsReporter.js.map +1 -0
- package/dist/voice-pipeline/VoicePipelineError.d.ts +44 -0
- package/dist/voice-pipeline/VoicePipelineError.d.ts.map +1 -0
- package/dist/voice-pipeline/VoicePipelineError.js +74 -0
- package/dist/voice-pipeline/VoicePipelineError.js.map +1 -0
- package/dist/voice-pipeline/env-constructor.d.ts +48 -0
- package/dist/voice-pipeline/env-constructor.d.ts.map +1 -0
- package/dist/voice-pipeline/env-constructor.js +85 -0
- package/dist/voice-pipeline/env-constructor.js.map +1 -0
- package/dist/voice-pipeline/index.d.ts +8 -1
- package/dist/voice-pipeline/index.d.ts.map +1 -1
- package/dist/voice-pipeline/index.js +9 -1
- package/dist/voice-pipeline/index.js.map +1 -1
- package/dist/voice-pipeline/providers/DeepgramStreamingSTT.d.ts +24 -1
- package/dist/voice-pipeline/providers/DeepgramStreamingSTT.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/DeepgramStreamingSTT.js +51 -0
- package/dist/voice-pipeline/providers/DeepgramStreamingSTT.js.map +1 -1
- package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.d.ts +17 -1
- package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.js +46 -0
- package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.js.map +1 -1
- package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.d.ts +16 -1
- package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.js +46 -0
- package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.js.map +1 -1
- package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.d.ts +16 -1
- package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.js +46 -0
- package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.js.map +1 -1
- package/dist/voice-pipeline/providers/OpenAIBatchTTS.d.ts +16 -1
- package/dist/voice-pipeline/providers/OpenAIBatchTTS.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/OpenAIBatchTTS.js +46 -0
- package/dist/voice-pipeline/providers/OpenAIBatchTTS.js.map +1 -1
- package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.d.ts +16 -1
- package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.js +46 -0
- package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.js.map +1 -1
- package/dist/voice-pipeline/providers/StreamingSTTChain.d.ts +78 -0
- package/dist/voice-pipeline/providers/StreamingSTTChain.d.ts.map +1 -0
- package/dist/voice-pipeline/providers/StreamingSTTChain.js +225 -0
- package/dist/voice-pipeline/providers/StreamingSTTChain.js.map +1 -0
- package/dist/voice-pipeline/providers/StreamingTTSChain.d.ts +67 -0
- package/dist/voice-pipeline/providers/StreamingTTSChain.d.ts.map +1 -0
- package/dist/voice-pipeline/providers/StreamingTTSChain.js +212 -0
- package/dist/voice-pipeline/providers/StreamingTTSChain.js.map +1 -0
- package/dist/voice-pipeline/providers/index.d.ts +2 -0
- package/dist/voice-pipeline/providers/index.d.ts.map +1 -1
- package/dist/voice-pipeline/providers/index.js +2 -0
- package/dist/voice-pipeline/providers/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAIRealtimeTTS.d.ts","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/OpenAIRealtimeTTS.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenAIRealtimeTTS.d.ts","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/OpenAIRealtimeTTS.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAC;AAY/B,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC7C,yCAAyC;IACzC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/F;AAiID,qBAAa,iBAAkB,YAAW,aAAa,EAAE,eAAe;IACtE,QAAQ,CAAC,UAAU,qBAAqB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsD;gBAEtE,MAAM,EAAE,uBAAuB;IAcrC,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA6BzC,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAM9E"}
|
|
@@ -11,6 +11,16 @@
|
|
|
11
11
|
import { EventEmitter } from 'node:events';
|
|
12
12
|
import WebSocket from 'ws';
|
|
13
13
|
import { ApiKeyPool } from '../../core/providers/ApiKeyPool.js';
|
|
14
|
+
import { defaultCapabilities, } from '../HealthyProvider.js';
|
|
15
|
+
import { VoicePipelineError } from '../VoicePipelineError.js';
|
|
16
|
+
async function defaultOpenAIProbe(apiKey) {
|
|
17
|
+
const start = Date.now();
|
|
18
|
+
const res = await fetch('https://api.openai.com/v1/models', {
|
|
19
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
20
|
+
signal: AbortSignal.timeout(1000),
|
|
21
|
+
});
|
|
22
|
+
return { ok: res.ok, status: res.status, latencyMs: Date.now() - start };
|
|
23
|
+
}
|
|
14
24
|
class OpenAIRealtimeTTSSession extends EventEmitter {
|
|
15
25
|
constructor(config, sessionConfig) {
|
|
16
26
|
super();
|
|
@@ -129,6 +139,42 @@ export class OpenAIRealtimeTTS {
|
|
|
129
139
|
this.providerId = 'openai-realtime';
|
|
130
140
|
this.config = config;
|
|
131
141
|
this.keyPool = new ApiKeyPool(config.apiKey);
|
|
142
|
+
this.priority = config.priority ?? 20;
|
|
143
|
+
this.capabilities = defaultCapabilities({
|
|
144
|
+
languages: ['*'],
|
|
145
|
+
streaming: true,
|
|
146
|
+
costTier: 'premium',
|
|
147
|
+
latencyClass: 'realtime',
|
|
148
|
+
...(config.capabilities ?? {}),
|
|
149
|
+
});
|
|
150
|
+
this.healthProbe = config.healthProbe ?? defaultOpenAIProbe;
|
|
151
|
+
}
|
|
152
|
+
async healthCheck() {
|
|
153
|
+
if (!this.keyPool.hasKeys) {
|
|
154
|
+
return { ok: false, error: { class: 'auth', message: 'no api key available' } };
|
|
155
|
+
}
|
|
156
|
+
const key = this.keyPool.next();
|
|
157
|
+
try {
|
|
158
|
+
const res = await this.healthProbe(key);
|
|
159
|
+
if (res.ok)
|
|
160
|
+
return { ok: true, latencyMs: res.latencyMs };
|
|
161
|
+
const classified = VoicePipelineError.classifyError(new Error(`HTTP ${res.status}`), { kind: 'tts', provider: this.providerId });
|
|
162
|
+
return {
|
|
163
|
+
ok: false,
|
|
164
|
+
latencyMs: res.latencyMs,
|
|
165
|
+
error: { class: classified.errorClass, message: `HTTP ${res.status}` },
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
const classified = VoicePipelineError.classifyError(err, {
|
|
170
|
+
kind: 'tts',
|
|
171
|
+
provider: this.providerId,
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
ok: false,
|
|
175
|
+
error: { class: classified.errorClass, message: classified.message },
|
|
176
|
+
};
|
|
177
|
+
}
|
|
132
178
|
}
|
|
133
179
|
async startSession(config) {
|
|
134
180
|
const resolvedConfig = { ...this.config, apiKey: this.keyPool.next() };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAIRealtimeTTS.js","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/OpenAIRealtimeTTS.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,SAAS,MAAM,IAAI,CAAC;AAO3B,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenAIRealtimeTTS.js","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/OpenAIRealtimeTTS.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/providers/StreamingSTTChain
|
|
3
|
+
*
|
|
4
|
+
* Priority-ordered fallback wrapper around multiple `IStreamingSTT`
|
|
5
|
+
* providers. On `startSession()` the chain tries providers in priority
|
|
6
|
+
* order; the first one whose `startSession()` resolves wins.
|
|
7
|
+
* Init-failure classification records to the circuit breaker so future
|
|
8
|
+
* sessions skip recently-tripped providers without the retry-latency
|
|
9
|
+
* penalty.
|
|
10
|
+
*
|
|
11
|
+
* This file implements Layer 2 of the resilience plan (init-time
|
|
12
|
+
* fallback). Layer 3 (mid-utterance failover via ring buffer) is added
|
|
13
|
+
* in a later task and plugs into the `wrapSession` seam exposed here.
|
|
14
|
+
*/
|
|
15
|
+
import type { IStreamingSTT, StreamingSTTSession, StreamingSTTConfig } from '../types.js';
|
|
16
|
+
import type { HealthyProvider } from '../HealthyProvider.js';
|
|
17
|
+
import { type HealthErrorClass } from '../VoicePipelineError.js';
|
|
18
|
+
import type { CircuitBreaker } from '../CircuitBreaker.js';
|
|
19
|
+
import type { VoiceMetricsReporter } from '../VoiceMetricsReporter.js';
|
|
20
|
+
export interface ProviderSelectedEvent {
|
|
21
|
+
kind: 'stt' | 'tts';
|
|
22
|
+
providerId: string;
|
|
23
|
+
attempt: number;
|
|
24
|
+
}
|
|
25
|
+
export interface ProviderFailedEvent {
|
|
26
|
+
kind: 'stt' | 'tts';
|
|
27
|
+
providerId: string;
|
|
28
|
+
errorClass: HealthErrorClass;
|
|
29
|
+
message: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ProviderFailoverEvent {
|
|
32
|
+
kind: 'stt' | 'tts';
|
|
33
|
+
from: string;
|
|
34
|
+
to: string;
|
|
35
|
+
reason: HealthErrorClass;
|
|
36
|
+
lostMs: number;
|
|
37
|
+
}
|
|
38
|
+
export interface StreamingSTTChainOptions {
|
|
39
|
+
breaker?: CircuitBreaker;
|
|
40
|
+
metrics?: VoiceMetricsReporter;
|
|
41
|
+
onProviderSelected?: (event: ProviderSelectedEvent) => void;
|
|
42
|
+
onProviderFailed?: (event: ProviderFailedEvent) => void;
|
|
43
|
+
onProviderFailover?: (event: ProviderFailoverEvent) => void;
|
|
44
|
+
/** When true, the chain tracks audio via a ring buffer and re-routes to
|
|
45
|
+
* the next backup on mid-session failure. Default: false. */
|
|
46
|
+
enableMidUtteranceFailover?: boolean;
|
|
47
|
+
/** Ring buffer capacity in ms for mid-utterance replay. Default 3000. */
|
|
48
|
+
ringBufferCapacityMs?: number;
|
|
49
|
+
/** Don't replay audio fragments shorter than this — just advance the
|
|
50
|
+
* next utterance to the backup. Default 400. */
|
|
51
|
+
minReplayMs?: number;
|
|
52
|
+
}
|
|
53
|
+
type STTProvider = IStreamingSTT & HealthyProvider;
|
|
54
|
+
export declare class StreamingSTTChain implements IStreamingSTT {
|
|
55
|
+
readonly providerId = "chain";
|
|
56
|
+
readonly isStreaming = false;
|
|
57
|
+
private readonly _providers;
|
|
58
|
+
private readonly opts;
|
|
59
|
+
private activeProviderId?;
|
|
60
|
+
constructor(providers: STTProvider[], opts?: StreamingSTTChainOptions);
|
|
61
|
+
/** Providers in priority order (primary first). Exposed for
|
|
62
|
+
* introspection by host apps and tests. */
|
|
63
|
+
get providers(): readonly STTProvider[];
|
|
64
|
+
get currentProviderId(): string | undefined;
|
|
65
|
+
startSession(config?: StreamingSTTConfig): Promise<StreamingSTTSession>;
|
|
66
|
+
private filterCandidates;
|
|
67
|
+
/**
|
|
68
|
+
* Wraps the session returned by a healthy provider. In init-time-only
|
|
69
|
+
* mode (enableMidUtteranceFailover=false) this is a pass-through. In
|
|
70
|
+
* failover mode the session is replaced with a facade that tees audio
|
|
71
|
+
* into a ring buffer, dedupes transcripts across providers, and on
|
|
72
|
+
* session error re-routes to the next candidate.
|
|
73
|
+
*/
|
|
74
|
+
private wrapSession;
|
|
75
|
+
private emitMetric;
|
|
76
|
+
}
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=StreamingSTTChain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingSTTChain.d.ts","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/StreamingSTTChain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAGnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EACV,oBAAoB,EAErB,MAAM,4BAA4B,CAAC;AAIpC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC5D,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACxD,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC5D;kEAC8D;IAC9D,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;qDACiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;AAEnD,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,WAAW,SAAS;IAE7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,gBAAgB,CAAC,CAAS;gBAEtB,SAAS,EAAE,WAAW,EAAE,EAAE,IAAI,GAAE,wBAA6B;IAQzE;gDAC4C;IAC5C,IAAI,SAAS,IAAI,SAAS,WAAW,EAAE,CAEtC;IAED,IAAI,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAE1C;IAEK,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA6D7E,OAAO,CAAC,gBAAgB;IAOxB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IA+InB,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/providers/StreamingSTTChain
|
|
3
|
+
*
|
|
4
|
+
* Priority-ordered fallback wrapper around multiple `IStreamingSTT`
|
|
5
|
+
* providers. On `startSession()` the chain tries providers in priority
|
|
6
|
+
* order; the first one whose `startSession()` resolves wins.
|
|
7
|
+
* Init-failure classification records to the circuit breaker so future
|
|
8
|
+
* sessions skip recently-tripped providers without the retry-latency
|
|
9
|
+
* penalty.
|
|
10
|
+
*
|
|
11
|
+
* This file implements Layer 2 of the resilience plan (init-time
|
|
12
|
+
* fallback). Layer 3 (mid-utterance failover via ring buffer) is added
|
|
13
|
+
* in a later task and plugs into the `wrapSession` seam exposed here.
|
|
14
|
+
*/
|
|
15
|
+
import { EventEmitter } from 'node:events';
|
|
16
|
+
import { VoicePipelineError, AggregateVoiceError, } from '../VoicePipelineError.js';
|
|
17
|
+
import { AudioRingBuffer } from '../AudioRingBuffer.js';
|
|
18
|
+
import { TranscriptDedupe } from '../TranscriptDedupe.js';
|
|
19
|
+
export class StreamingSTTChain {
|
|
20
|
+
constructor(providers, opts = {}) {
|
|
21
|
+
this.providerId = 'chain';
|
|
22
|
+
this.isStreaming = false;
|
|
23
|
+
if (providers.length === 0) {
|
|
24
|
+
throw new Error('StreamingSTTChain requires at least one provider');
|
|
25
|
+
}
|
|
26
|
+
this._providers = [...providers].sort((a, b) => a.priority - b.priority);
|
|
27
|
+
this.opts = opts;
|
|
28
|
+
}
|
|
29
|
+
/** Providers in priority order (primary first). Exposed for
|
|
30
|
+
* introspection by host apps and tests. */
|
|
31
|
+
get providers() {
|
|
32
|
+
return this._providers;
|
|
33
|
+
}
|
|
34
|
+
get currentProviderId() {
|
|
35
|
+
return this.activeProviderId;
|
|
36
|
+
}
|
|
37
|
+
async startSession(config) {
|
|
38
|
+
const candidates = this.filterCandidates();
|
|
39
|
+
if (candidates.length === 0) {
|
|
40
|
+
this.emitMetric({
|
|
41
|
+
type: 'provider_unavailable',
|
|
42
|
+
kind: 'stt',
|
|
43
|
+
checkedProviders: this._providers.map((p) => p.providerId),
|
|
44
|
+
});
|
|
45
|
+
throw new Error('No STT providers available (all tripped or filtered)');
|
|
46
|
+
}
|
|
47
|
+
const attempts = [];
|
|
48
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
49
|
+
const provider = candidates[i];
|
|
50
|
+
try {
|
|
51
|
+
const session = await provider.startSession(config);
|
|
52
|
+
this.activeProviderId = provider.providerId;
|
|
53
|
+
const evt = {
|
|
54
|
+
kind: 'stt',
|
|
55
|
+
providerId: provider.providerId,
|
|
56
|
+
attempt: i + 1,
|
|
57
|
+
};
|
|
58
|
+
this.opts.onProviderSelected?.(evt);
|
|
59
|
+
this.emitMetric({ type: 'provider_selected', ...evt });
|
|
60
|
+
this.opts.breaker?.recordSuccess(provider.providerId);
|
|
61
|
+
return this.wrapSession(session, provider, candidates.slice(i + 1), config);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const classified = VoicePipelineError.classifyError(err, {
|
|
65
|
+
kind: 'stt',
|
|
66
|
+
provider: provider.providerId,
|
|
67
|
+
});
|
|
68
|
+
attempts.push(classified);
|
|
69
|
+
const failEvt = {
|
|
70
|
+
kind: 'stt',
|
|
71
|
+
providerId: provider.providerId,
|
|
72
|
+
errorClass: classified.errorClass,
|
|
73
|
+
message: classified.message,
|
|
74
|
+
};
|
|
75
|
+
this.opts.onProviderFailed?.(failEvt);
|
|
76
|
+
this.emitMetric({ type: 'provider_failed', ...failEvt });
|
|
77
|
+
this.opts.breaker?.recordFailure(provider.providerId, classified.errorClass);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.emitMetric({
|
|
81
|
+
type: 'provider_unavailable',
|
|
82
|
+
kind: 'stt',
|
|
83
|
+
checkedProviders: candidates.map((p) => p.providerId),
|
|
84
|
+
});
|
|
85
|
+
throw new AggregateVoiceError(attempts);
|
|
86
|
+
}
|
|
87
|
+
filterCandidates() {
|
|
88
|
+
if (!this.opts.breaker)
|
|
89
|
+
return this._providers;
|
|
90
|
+
return this._providers.filter((p) => this.opts.breaker.isAvailable(p.providerId));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Wraps the session returned by a healthy provider. In init-time-only
|
|
94
|
+
* mode (enableMidUtteranceFailover=false) this is a pass-through. In
|
|
95
|
+
* failover mode the session is replaced with a facade that tees audio
|
|
96
|
+
* into a ring buffer, dedupes transcripts across providers, and on
|
|
97
|
+
* session error re-routes to the next candidate.
|
|
98
|
+
*/
|
|
99
|
+
wrapSession(initial, initialProvider, candidates, config) {
|
|
100
|
+
if (!this.opts.enableMidUtteranceFailover)
|
|
101
|
+
return initial;
|
|
102
|
+
const ring = new AudioRingBuffer({
|
|
103
|
+
capacityMs: this.opts.ringBufferCapacityMs ?? 3000,
|
|
104
|
+
sampleRate: 16000,
|
|
105
|
+
});
|
|
106
|
+
const dedupe = new TranscriptDedupe();
|
|
107
|
+
const minReplayMs = this.opts.minReplayMs ?? 400;
|
|
108
|
+
const facade = new EventEmitter();
|
|
109
|
+
let currentSession = initial;
|
|
110
|
+
let currentProvider = initialProvider;
|
|
111
|
+
let remaining = [...candidates];
|
|
112
|
+
let isFailingOver = false;
|
|
113
|
+
const attach = (session, providerId) => {
|
|
114
|
+
session.on('transcript', (evt) => {
|
|
115
|
+
const r = dedupe.evaluate({
|
|
116
|
+
provider: providerId,
|
|
117
|
+
text: evt.text,
|
|
118
|
+
audioStartMs: evt.audioStartMs ?? 0,
|
|
119
|
+
audioEndMs: evt.audioEndMs ?? 0,
|
|
120
|
+
isFinal: evt.isFinal,
|
|
121
|
+
});
|
|
122
|
+
if (r.isDuplicate)
|
|
123
|
+
return;
|
|
124
|
+
facade.emit('transcript', evt);
|
|
125
|
+
});
|
|
126
|
+
for (const passthrough of ['vad', 'speech_start', 'speech_end']) {
|
|
127
|
+
session.on(passthrough, (...args) => {
|
|
128
|
+
facade.emit(passthrough, ...args);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
session.on('error', (err) => {
|
|
132
|
+
void tryFailover(err);
|
|
133
|
+
});
|
|
134
|
+
session.on('close', () => {
|
|
135
|
+
// Natural close on the active session is a failover trigger so the
|
|
136
|
+
// user doesn't silently lose voice mid-turn. If the chain was asked
|
|
137
|
+
// to close() externally, isFailingOver stays false and the close
|
|
138
|
+
// propagates.
|
|
139
|
+
if (!isFailingOver && currentSession === session) {
|
|
140
|
+
void tryFailover(undefined);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
const tryFailover = async (err) => {
|
|
145
|
+
if (isFailingOver)
|
|
146
|
+
return;
|
|
147
|
+
isFailingOver = true;
|
|
148
|
+
const startedAt = Date.now();
|
|
149
|
+
const classified = VoicePipelineError.classifyError(err ?? new Error('session ended'), { kind: 'stt', provider: currentProvider.providerId });
|
|
150
|
+
this.opts.breaker?.recordFailure(currentProvider.providerId, classified.errorClass);
|
|
151
|
+
const bufferedFrames = ring.snapshot();
|
|
152
|
+
const bufferedMs = ring.durationMs();
|
|
153
|
+
for (const backup of remaining) {
|
|
154
|
+
if (this.opts.breaker &&
|
|
155
|
+
!this.opts.breaker.isAvailable(backup.providerId)) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const session = await backup.startSession(config);
|
|
160
|
+
attach(session, backup.providerId);
|
|
161
|
+
if (bufferedMs >= minReplayMs) {
|
|
162
|
+
for (const f of bufferedFrames) {
|
|
163
|
+
try {
|
|
164
|
+
await session.pushAudio(f);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
/* tolerate frame-level push failures during replay */
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
currentSession = session;
|
|
172
|
+
currentProvider = backup;
|
|
173
|
+
remaining = remaining.filter((c) => c !== backup);
|
|
174
|
+
this.activeProviderId = backup.providerId;
|
|
175
|
+
const lostMs = Date.now() - startedAt;
|
|
176
|
+
const evt = {
|
|
177
|
+
kind: 'stt',
|
|
178
|
+
from: initialProvider.providerId,
|
|
179
|
+
to: backup.providerId,
|
|
180
|
+
reason: classified.errorClass,
|
|
181
|
+
lostMs,
|
|
182
|
+
};
|
|
183
|
+
this.opts.onProviderFailover?.(evt);
|
|
184
|
+
this.emitMetric({ type: 'provider_failover', ...evt });
|
|
185
|
+
isFailingOver = false;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
catch (backupErr) {
|
|
189
|
+
const backClass = VoicePipelineError.classifyError(backupErr, {
|
|
190
|
+
kind: 'stt',
|
|
191
|
+
provider: backup.providerId,
|
|
192
|
+
});
|
|
193
|
+
this.opts.breaker?.recordFailure(backup.providerId, backClass.errorClass);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// All backups exhausted — propagate to the facade consumer.
|
|
197
|
+
facade.emit('error', new AggregateVoiceError([classified]));
|
|
198
|
+
isFailingOver = false;
|
|
199
|
+
};
|
|
200
|
+
attach(initial, initialProvider.providerId);
|
|
201
|
+
// The returned object must conform to StreamingSTTSession (EventEmitter
|
|
202
|
+
// with pushAudio + close). We build that explicitly so TS sees the
|
|
203
|
+
// right shape.
|
|
204
|
+
const wrapped = Object.assign(facade, {
|
|
205
|
+
providerId: 'chain',
|
|
206
|
+
pushAudio: async (frame) => {
|
|
207
|
+
ring.push(frame);
|
|
208
|
+
try {
|
|
209
|
+
await currentSession.pushAudio(frame);
|
|
210
|
+
}
|
|
211
|
+
catch (pushErr) {
|
|
212
|
+
void tryFailover(pushErr);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
close: async () => {
|
|
216
|
+
await currentSession.close();
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
return wrapped;
|
|
220
|
+
}
|
|
221
|
+
emitMetric(event) {
|
|
222
|
+
this.opts.metrics?.emit(event);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=StreamingSTTChain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingSTTChain.js","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/StreamingSTTChain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/providers/StreamingTTSChain
|
|
3
|
+
*
|
|
4
|
+
* Priority-ordered fallback wrapper around multiple `IStreamingTTS`
|
|
5
|
+
* providers. Mirrors `StreamingSTTChain` semantics for outbound synthesis.
|
|
6
|
+
*
|
|
7
|
+
* Mid-synthesis failover is simpler than mid-utterance STT failover
|
|
8
|
+
* because TTS is one-way (text in, audio out). The chain accumulates
|
|
9
|
+
* tokens pushed to the primary and, on primary failure, re-sends them
|
|
10
|
+
* to the backup. Clients may use the first backup audio chunk's
|
|
11
|
+
* `fadeInMs` hint to crossfade between timbres.
|
|
12
|
+
*/
|
|
13
|
+
import type { IStreamingTTS, StreamingTTSSession, StreamingTTSConfig } from '../types.js';
|
|
14
|
+
import type { HealthyProvider } from '../HealthyProvider.js';
|
|
15
|
+
import { type HealthErrorClass } from '../VoicePipelineError.js';
|
|
16
|
+
import type { CircuitBreaker } from '../CircuitBreaker.js';
|
|
17
|
+
import type { VoiceMetricsReporter } from '../VoiceMetricsReporter.js';
|
|
18
|
+
export interface TTSProviderSelectedEvent {
|
|
19
|
+
kind: 'tts';
|
|
20
|
+
providerId: string;
|
|
21
|
+
attempt: number;
|
|
22
|
+
}
|
|
23
|
+
export interface TTSProviderFailedEvent {
|
|
24
|
+
kind: 'tts';
|
|
25
|
+
providerId: string;
|
|
26
|
+
errorClass: HealthErrorClass;
|
|
27
|
+
message: string;
|
|
28
|
+
}
|
|
29
|
+
export interface TTSProviderFailoverEvent {
|
|
30
|
+
kind: 'tts';
|
|
31
|
+
from: string;
|
|
32
|
+
to: string;
|
|
33
|
+
reason: HealthErrorClass;
|
|
34
|
+
lostMs: number;
|
|
35
|
+
}
|
|
36
|
+
export interface StreamingTTSChainOptions {
|
|
37
|
+
breaker?: CircuitBreaker;
|
|
38
|
+
metrics?: VoiceMetricsReporter;
|
|
39
|
+
onProviderSelected?: (event: TTSProviderSelectedEvent) => void;
|
|
40
|
+
onProviderFailed?: (event: TTSProviderFailedEvent) => void;
|
|
41
|
+
onProviderFailover?: (event: TTSProviderFailoverEvent) => void;
|
|
42
|
+
/** When true, the chain tracks accumulated tokens and re-submits them
|
|
43
|
+
* to the next backup if the primary errors mid-synthesis. */
|
|
44
|
+
enableMidSynthesisFailover?: boolean;
|
|
45
|
+
}
|
|
46
|
+
type TTSProvider = IStreamingTTS & HealthyProvider;
|
|
47
|
+
export declare class StreamingTTSChain implements IStreamingTTS {
|
|
48
|
+
readonly providerId = "chain";
|
|
49
|
+
private readonly _providers;
|
|
50
|
+
private readonly opts;
|
|
51
|
+
private activeProviderId?;
|
|
52
|
+
constructor(providers: TTSProvider[], opts?: StreamingTTSChainOptions);
|
|
53
|
+
get providers(): readonly TTSProvider[];
|
|
54
|
+
get currentProviderId(): string | undefined;
|
|
55
|
+
startSession(config?: StreamingTTSConfig): Promise<StreamingTTSSession>;
|
|
56
|
+
private filterCandidates;
|
|
57
|
+
/**
|
|
58
|
+
* Wraps a session for mid-synthesis failover. The facade tees pushTokens
|
|
59
|
+
* calls into an accumulator and, when the primary emits 'error',
|
|
60
|
+
* opens a new session on the next backup and replays the accumulator
|
|
61
|
+
* before returning control.
|
|
62
|
+
*/
|
|
63
|
+
private wrapSession;
|
|
64
|
+
private emitMetric;
|
|
65
|
+
}
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=StreamingTTSChain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingTTSChain.d.ts","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/StreamingTTSChain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EACV,oBAAoB,EAErB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,KAAK,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,KAAK,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC/D,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAC3D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC/D;kEAC8D;IAC9D,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,KAAK,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;AAEnD,qBAAa,iBAAkB,YAAW,aAAa;IACrD,QAAQ,CAAC,UAAU,WAAW;IAE9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,gBAAgB,CAAC,CAAS;gBAEtB,SAAS,EAAE,WAAW,EAAE,EAAE,IAAI,GAAE,wBAA6B;IAQzE,IAAI,SAAS,IAAI,SAAS,WAAW,EAAE,CAEtC;IAED,IAAI,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAE1C;IAEK,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA6D7E,OAAO,CAAC,gBAAgB;IAOxB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAsInB,OAAO,CAAC,UAAU;CAGnB"}
|