@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.
Files changed (87) hide show
  1. package/README.md +1 -0
  2. package/dist/api/editImage.d.ts +21 -0
  3. package/dist/api/editImage.d.ts.map +1 -1
  4. package/dist/api/editImage.js +30 -2
  5. package/dist/api/editImage.js.map +1 -1
  6. package/dist/api/generateImage.d.ts +12 -1
  7. package/dist/api/generateImage.d.ts.map +1 -1
  8. package/dist/api/generateImage.js +7 -2
  9. package/dist/api/generateImage.js.map +1 -1
  10. package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts.map +1 -1
  11. package/dist/core/llm/providers/implementations/AnthropicProvider.js +71 -12
  12. package/dist/core/llm/providers/implementations/AnthropicProvider.js.map +1 -1
  13. package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts.map +1 -1
  14. package/dist/core/llm/providers/implementations/OpenAIProvider.js +38 -11
  15. package/dist/core/llm/providers/implementations/OpenAIProvider.js.map +1 -1
  16. package/dist/media/images/providers/ReplicateImageProvider.d.ts.map +1 -1
  17. package/dist/media/images/providers/ReplicateImageProvider.js +7 -0
  18. package/dist/media/images/providers/ReplicateImageProvider.js.map +1 -1
  19. package/dist/voice-pipeline/AudioRingBuffer.d.ts +28 -0
  20. package/dist/voice-pipeline/AudioRingBuffer.d.ts.map +1 -0
  21. package/dist/voice-pipeline/AudioRingBuffer.js +43 -0
  22. package/dist/voice-pipeline/AudioRingBuffer.js.map +1 -0
  23. package/dist/voice-pipeline/CircuitBreaker.d.ts +42 -0
  24. package/dist/voice-pipeline/CircuitBreaker.d.ts.map +1 -0
  25. package/dist/voice-pipeline/CircuitBreaker.js +96 -0
  26. package/dist/voice-pipeline/CircuitBreaker.js.map +1 -0
  27. package/dist/voice-pipeline/HealthyProvider.d.ts +44 -0
  28. package/dist/voice-pipeline/HealthyProvider.d.ts.map +1 -0
  29. package/dist/voice-pipeline/HealthyProvider.js +29 -0
  30. package/dist/voice-pipeline/HealthyProvider.js.map +1 -0
  31. package/dist/voice-pipeline/TranscriptDedupe.d.ts +43 -0
  32. package/dist/voice-pipeline/TranscriptDedupe.d.ts.map +1 -0
  33. package/dist/voice-pipeline/TranscriptDedupe.js +96 -0
  34. package/dist/voice-pipeline/TranscriptDedupe.js.map +1 -0
  35. package/dist/voice-pipeline/VoiceMetricsReporter.d.ts +48 -0
  36. package/dist/voice-pipeline/VoiceMetricsReporter.d.ts.map +1 -0
  37. package/dist/voice-pipeline/VoiceMetricsReporter.js +33 -0
  38. package/dist/voice-pipeline/VoiceMetricsReporter.js.map +1 -0
  39. package/dist/voice-pipeline/VoicePipelineError.d.ts +44 -0
  40. package/dist/voice-pipeline/VoicePipelineError.d.ts.map +1 -0
  41. package/dist/voice-pipeline/VoicePipelineError.js +74 -0
  42. package/dist/voice-pipeline/VoicePipelineError.js.map +1 -0
  43. package/dist/voice-pipeline/env-constructor.d.ts +48 -0
  44. package/dist/voice-pipeline/env-constructor.d.ts.map +1 -0
  45. package/dist/voice-pipeline/env-constructor.js +85 -0
  46. package/dist/voice-pipeline/env-constructor.js.map +1 -0
  47. package/dist/voice-pipeline/index.d.ts +8 -1
  48. package/dist/voice-pipeline/index.d.ts.map +1 -1
  49. package/dist/voice-pipeline/index.js +9 -1
  50. package/dist/voice-pipeline/index.js.map +1 -1
  51. package/dist/voice-pipeline/providers/DeepgramStreamingSTT.d.ts +24 -1
  52. package/dist/voice-pipeline/providers/DeepgramStreamingSTT.d.ts.map +1 -1
  53. package/dist/voice-pipeline/providers/DeepgramStreamingSTT.js +51 -0
  54. package/dist/voice-pipeline/providers/DeepgramStreamingSTT.js.map +1 -1
  55. package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.d.ts +17 -1
  56. package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.d.ts.map +1 -1
  57. package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.js +46 -0
  58. package/dist/voice-pipeline/providers/ElevenLabsBatchTTS.js.map +1 -1
  59. package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.d.ts +16 -1
  60. package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.d.ts.map +1 -1
  61. package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.js +46 -0
  62. package/dist/voice-pipeline/providers/ElevenLabsStreamingSTT.js.map +1 -1
  63. package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.d.ts +16 -1
  64. package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.d.ts.map +1 -1
  65. package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.js +46 -0
  66. package/dist/voice-pipeline/providers/ElevenLabsStreamingTTS.js.map +1 -1
  67. package/dist/voice-pipeline/providers/OpenAIBatchTTS.d.ts +16 -1
  68. package/dist/voice-pipeline/providers/OpenAIBatchTTS.d.ts.map +1 -1
  69. package/dist/voice-pipeline/providers/OpenAIBatchTTS.js +46 -0
  70. package/dist/voice-pipeline/providers/OpenAIBatchTTS.js.map +1 -1
  71. package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.d.ts +16 -1
  72. package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.d.ts.map +1 -1
  73. package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.js +46 -0
  74. package/dist/voice-pipeline/providers/OpenAIRealtimeTTS.js.map +1 -1
  75. package/dist/voice-pipeline/providers/StreamingSTTChain.d.ts +78 -0
  76. package/dist/voice-pipeline/providers/StreamingSTTChain.d.ts.map +1 -0
  77. package/dist/voice-pipeline/providers/StreamingSTTChain.js +225 -0
  78. package/dist/voice-pipeline/providers/StreamingSTTChain.js.map +1 -0
  79. package/dist/voice-pipeline/providers/StreamingTTSChain.d.ts +67 -0
  80. package/dist/voice-pipeline/providers/StreamingTTSChain.d.ts.map +1 -0
  81. package/dist/voice-pipeline/providers/StreamingTTSChain.js +212 -0
  82. package/dist/voice-pipeline/providers/StreamingTTSChain.js.map +1 -0
  83. package/dist/voice-pipeline/providers/index.d.ts +2 -0
  84. package/dist/voice-pipeline/providers/index.d.ts.map +1 -1
  85. package/dist/voice-pipeline/providers/index.js +2 -0
  86. package/dist/voice-pipeline/providers/index.js.map +1 -1
  87. package/package.json +1 -1
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @module voice-pipeline/TranscriptDedupe
3
+ *
4
+ * Duplicate-transcript detector used by StreamingSTTChain after a mid-
5
+ * utterance failover. The backup provider replays the ring buffer and
6
+ * re-transcribes audio the primary already saw; without dedupe the session
7
+ * sees "hello world" twice.
8
+ *
9
+ * Dedupe signal: audio-clock overlap (primary fact) + fuzzy string match
10
+ * (tie-breaker). Two transcripts overlap if their [audioStartMs, audioEndMs]
11
+ * ranges intersect; when they do, we compare normalized text.
12
+ *
13
+ * Same-provider observations are never considered duplicates — interim
14
+ * transcripts from a single streaming provider are part of its protocol.
15
+ */
16
+ const PUNCT_RE = /[.,!?;:"'()\[\]{}]/g;
17
+ const WS_RE = /\s+/g;
18
+ function normalize(text) {
19
+ return text.toLowerCase().replace(PUNCT_RE, '').replace(WS_RE, ' ').trim();
20
+ }
21
+ function tokenSet(text) {
22
+ return new Set(normalize(text).split(' ').filter(Boolean));
23
+ }
24
+ function tokenSetSimilarity(a, b) {
25
+ const ta = tokenSet(a);
26
+ const tb = tokenSet(b);
27
+ if (ta.size === 0 && tb.size === 0)
28
+ return 1;
29
+ if (ta.size === 0 || tb.size === 0)
30
+ return 0;
31
+ let intersect = 0;
32
+ for (const t of ta)
33
+ if (tb.has(t))
34
+ intersect++;
35
+ return intersect / Math.max(ta.size, tb.size);
36
+ }
37
+ function rangesOverlap(a, b) {
38
+ return a.audioStartMs < b.audioEndMs && b.audioStartMs < a.audioEndMs;
39
+ }
40
+ export class TranscriptDedupe {
41
+ constructor(opts = {}) {
42
+ this.recent = [];
43
+ this.fuzzyThreshold = opts.fuzzyThreshold ?? 0.85;
44
+ this.retainMs = opts.retainMs ?? 10000;
45
+ }
46
+ evaluate(obs) {
47
+ this.prune(obs.audioEndMs);
48
+ for (const prev of this.recent) {
49
+ if (prev.provider === obs.provider)
50
+ continue;
51
+ if (!rangesOverlap(prev, obs))
52
+ continue;
53
+ const na = normalize(prev.text);
54
+ const nb = normalize(obs.text);
55
+ if (na === nb) {
56
+ this.recent.push(obs);
57
+ return {
58
+ isDuplicate: true,
59
+ reason: 'exact',
60
+ against: { provider: prev.provider, text: prev.text },
61
+ };
62
+ }
63
+ // Longer transcript subsumes shorter one (primary saw more audio by
64
+ // the time backup caught up — suppress the backup's shorter view).
65
+ if (na.includes(nb) || nb.includes(na)) {
66
+ if (na.length >= nb.length) {
67
+ this.recent.push(obs);
68
+ return {
69
+ isDuplicate: true,
70
+ reason: 'superset',
71
+ against: { provider: prev.provider, text: prev.text },
72
+ };
73
+ }
74
+ }
75
+ const sim = tokenSetSimilarity(prev.text, obs.text);
76
+ if (sim >= this.fuzzyThreshold) {
77
+ this.recent.push(obs);
78
+ return {
79
+ isDuplicate: true,
80
+ reason: 'fuzzy',
81
+ against: { provider: prev.provider, text: prev.text },
82
+ };
83
+ }
84
+ }
85
+ this.recent.push(obs);
86
+ return { isDuplicate: false };
87
+ }
88
+ reset() {
89
+ this.recent = [];
90
+ }
91
+ prune(upToMs) {
92
+ const cutoff = upToMs - this.retainMs;
93
+ this.recent = this.recent.filter((o) => o.audioEndMs >= cutoff);
94
+ }
95
+ }
96
+ //# sourceMappingURL=TranscriptDedupe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TranscriptDedupe.js","sourceRoot":"","sources":["../../src/voice-pipeline/TranscriptDedupe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @module voice-pipeline/VoiceMetricsReporter
3
+ *
4
+ * Typed pub/sub bus for voice-pipeline lifecycle events. Chains and
5
+ * circuit breakers emit structured events here; host applications
6
+ * subscribe to forward them to clients (WebSocket frames), metrics
7
+ * systems (Prometheus, Datadog), or logs.
8
+ *
9
+ * Listener errors are swallowed — one bad subscriber must not poison the
10
+ * fan-out path for others.
11
+ */
12
+ import type { HealthErrorClass } from './VoicePipelineError.js';
13
+ export type VoiceMetricEvent = {
14
+ type: 'provider_selected';
15
+ kind: 'stt' | 'tts';
16
+ providerId: string;
17
+ attempt: number;
18
+ } | {
19
+ type: 'provider_failed';
20
+ kind: 'stt' | 'tts';
21
+ providerId: string;
22
+ errorClass: HealthErrorClass;
23
+ message: string;
24
+ } | {
25
+ type: 'provider_failover';
26
+ kind: 'stt' | 'tts';
27
+ from: string;
28
+ to: string;
29
+ reason: HealthErrorClass;
30
+ lostMs: number;
31
+ } | {
32
+ type: 'provider_degraded';
33
+ kind: 'stt' | 'tts';
34
+ providerId: string;
35
+ latencyMs: number;
36
+ thresholdMs: number;
37
+ } | {
38
+ type: 'provider_unavailable';
39
+ kind: 'stt' | 'tts';
40
+ checkedProviders: string[];
41
+ };
42
+ export type VoiceMetricListener = (event: VoiceMetricEvent) => void;
43
+ export declare class VoiceMetricsReporter {
44
+ private readonly listeners;
45
+ subscribe(fn: VoiceMetricListener): () => void;
46
+ emit(event: VoiceMetricEvent): void;
47
+ }
48
+ //# sourceMappingURL=VoiceMetricsReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceMetricsReporter.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/VoiceMetricsReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GACxB;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,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,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEpE,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAE5D,SAAS,CAAC,EAAE,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAO9C,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;CASpC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @module voice-pipeline/VoiceMetricsReporter
3
+ *
4
+ * Typed pub/sub bus for voice-pipeline lifecycle events. Chains and
5
+ * circuit breakers emit structured events here; host applications
6
+ * subscribe to forward them to clients (WebSocket frames), metrics
7
+ * systems (Prometheus, Datadog), or logs.
8
+ *
9
+ * Listener errors are swallowed — one bad subscriber must not poison the
10
+ * fan-out path for others.
11
+ */
12
+ export class VoiceMetricsReporter {
13
+ constructor() {
14
+ this.listeners = new Set();
15
+ }
16
+ subscribe(fn) {
17
+ this.listeners.add(fn);
18
+ return () => {
19
+ this.listeners.delete(fn);
20
+ };
21
+ }
22
+ emit(event) {
23
+ for (const fn of this.listeners) {
24
+ try {
25
+ fn(event);
26
+ }
27
+ catch {
28
+ /* swallow — one bad listener must not poison the rest */
29
+ }
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=VoiceMetricsReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceMetricsReporter.js","sourceRoot":"","sources":["../../src/voice-pipeline/VoiceMetricsReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAyCH,MAAM,OAAO,oBAAoB;IAAjC;QACmB,cAAS,GAAG,IAAI,GAAG,EAAuB,CAAC;IAkB9D,CAAC;IAhBC,SAAS,CAAC,EAAuB;QAC/B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAuB;QAC1B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,EAAE,CAAC,KAAK,CAAC,CAAC;YACZ,CAAC;YAAC,MAAM,CAAC;gBACP,yDAAyD;YAC3D,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @module voice-pipeline/VoicePipelineError
3
+ *
4
+ * Structured error class for voice pipeline failures. Carries enough shape
5
+ * for chains and circuit breakers to classify and react without stringly
6
+ * matching error.message.
7
+ */
8
+ export type HealthErrorClass = 'auth' | 'quota' | 'network' | 'service' | 'unknown';
9
+ export interface VoicePipelineErrorInit {
10
+ kind: 'stt' | 'tts' | 'transport';
11
+ provider: string;
12
+ errorClass: HealthErrorClass;
13
+ message: string;
14
+ cause?: unknown;
15
+ retryable: boolean;
16
+ }
17
+ export declare class VoicePipelineError extends Error {
18
+ readonly kind: VoicePipelineErrorInit['kind'];
19
+ readonly provider: string;
20
+ readonly errorClass: HealthErrorClass;
21
+ readonly retryable: boolean;
22
+ readonly cause?: unknown;
23
+ constructor(init: VoicePipelineErrorInit);
24
+ /**
25
+ * Best-effort classification of an arbitrary error into a voice-pipeline
26
+ * error with a well-known errorClass. Preserves the original error as
27
+ * `cause` so upstream inspection can still recover provider-specific
28
+ * detail.
29
+ */
30
+ static classifyError(err: unknown, meta: {
31
+ kind: VoicePipelineErrorInit['kind'];
32
+ provider: string;
33
+ }): VoicePipelineError;
34
+ }
35
+ /**
36
+ * Aggregate thrown by `StreamingSTTChain` / `StreamingTTSChain` when every
37
+ * candidate provider fails. Carries the per-provider error list so callers
38
+ * can display a breakdown rather than a single confusing message.
39
+ */
40
+ export declare class AggregateVoiceError extends Error {
41
+ readonly attempts: VoicePipelineError[];
42
+ constructor(attempts: VoicePipelineError[]);
43
+ }
44
+ //# sourceMappingURL=VoicePipelineError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoicePipelineError.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/VoicePipelineError.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,OAAO,GACP,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,WAAW,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEb,IAAI,EAAE,sBAAsB;IAUxC;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAClB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;QAAE,IAAI,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAC/D,kBAAkB;CAoCtB;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;gBAE5B,QAAQ,EAAE,kBAAkB,EAAE;CAQ3C"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @module voice-pipeline/VoicePipelineError
3
+ *
4
+ * Structured error class for voice pipeline failures. Carries enough shape
5
+ * for chains and circuit breakers to classify and react without stringly
6
+ * matching error.message.
7
+ */
8
+ export class VoicePipelineError extends Error {
9
+ constructor(init) {
10
+ super(init.message);
11
+ this.name = 'VoicePipelineError';
12
+ this.kind = init.kind;
13
+ this.provider = init.provider;
14
+ this.errorClass = init.errorClass;
15
+ this.retryable = init.retryable;
16
+ this.cause = init.cause;
17
+ }
18
+ /**
19
+ * Best-effort classification of an arbitrary error into a voice-pipeline
20
+ * error with a well-known errorClass. Preserves the original error as
21
+ * `cause` so upstream inspection can still recover provider-specific
22
+ * detail.
23
+ */
24
+ static classifyError(err, meta) {
25
+ const raw = err instanceof Error ? err : new Error(String(err));
26
+ const msg = raw.message ?? '';
27
+ const code = err?.code ?? '';
28
+ let errorClass = 'unknown';
29
+ let retryable = true;
30
+ if (/\b401\b|unauthori[sz]ed|invalid api key|forbidden|\b403\b/i.test(msg)) {
31
+ errorClass = 'auth';
32
+ retryable = false;
33
+ }
34
+ else if (/\b429\b|rate.?limit|too many/i.test(msg)) {
35
+ errorClass = 'quota';
36
+ retryable = true;
37
+ }
38
+ else if (/\b5\d\d\b|internal server|bad gateway|gateway timeout|service unavailable/i.test(msg)) {
39
+ errorClass = 'service';
40
+ retryable = true;
41
+ }
42
+ else if (code === 'ECONNRESET' ||
43
+ code === 'ETIMEDOUT' ||
44
+ code === 'ENOTFOUND' ||
45
+ /econnreset|etimedout|enotfound|socket hang up|network/i.test(msg)) {
46
+ errorClass = 'network';
47
+ retryable = true;
48
+ }
49
+ return new VoicePipelineError({
50
+ kind: meta.kind,
51
+ provider: meta.provider,
52
+ errorClass,
53
+ message: msg || 'unknown voice pipeline error',
54
+ cause: err,
55
+ retryable,
56
+ });
57
+ }
58
+ }
59
+ /**
60
+ * Aggregate thrown by `StreamingSTTChain` / `StreamingTTSChain` when every
61
+ * candidate provider fails. Carries the per-provider error list so callers
62
+ * can display a breakdown rather than a single confusing message.
63
+ */
64
+ export class AggregateVoiceError extends Error {
65
+ constructor(attempts) {
66
+ const summary = attempts
67
+ .map((a) => `${a.provider}: ${a.errorClass} \u2014 ${a.message}`)
68
+ .join('; ');
69
+ super(`All ${attempts.length} providers failed \u2014 ${summary}`);
70
+ this.name = 'AggregateVoiceError';
71
+ this.attempts = attempts;
72
+ }
73
+ }
74
+ //# sourceMappingURL=VoicePipelineError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoicePipelineError.js","sourceRoot":"","sources":["../../src/voice-pipeline/VoicePipelineError.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAO3C,YAAY,IAA4B;QACtC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAClB,GAAY,EACZ,IAAgE;QAEhE,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAI,GAAgC,EAAE,IAAI,IAAI,EAAE,CAAC;QAE3D,IAAI,UAAU,GAAqB,SAAS,CAAC;QAC7C,IAAI,SAAS,GAAG,IAAI,CAAC;QAErB,IAAI,4DAA4D,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3E,UAAU,GAAG,MAAM,CAAC;YACpB,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;aAAM,IAAI,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,UAAU,GAAG,OAAO,CAAC;YACrB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,IAAI,4EAA4E,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClG,UAAU,GAAG,SAAS,CAAC;YACvB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,IACL,IAAI,KAAK,YAAY;YACrB,IAAI,KAAK,WAAW;YACpB,IAAI,KAAK,WAAW;YACpB,wDAAwD,CAAC,IAAI,CAAC,GAAG,CAAC,EAClE,CAAC;YACD,UAAU,GAAG,SAAS,CAAC;YACvB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,OAAO,IAAI,kBAAkB,CAAC;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU;YACV,OAAO,EAAE,GAAG,IAAI,8BAA8B;YAC9C,KAAK,EAAE,GAAG;YACV,SAAS;SACV,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAG5C,YAAY,QAA8B;QACxC,MAAM,OAAO,GAAG,QAAQ;aACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,UAAU,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;aAChE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,KAAK,CAAC,OAAO,QAAQ,CAAC,MAAM,4BAA4B,OAAO,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @module voice-pipeline/env-constructor
3
+ *
4
+ * Batteries-included constructor for `StreamingSTTChain` +
5
+ * `StreamingTTSChain`. Reads provider keys from an env-like object and
6
+ * builds priority-ordered chains with shared circuit breaker and metrics
7
+ * reporter. Host apps can skip the manual wiring and use this factory as
8
+ * the default integration point.
9
+ */
10
+ import { StreamingSTTChain } from './providers/StreamingSTTChain.js';
11
+ import { StreamingTTSChain } from './providers/StreamingTTSChain.js';
12
+ import { CircuitBreaker } from './CircuitBreaker.js';
13
+ import { VoiceMetricsReporter } from './VoiceMetricsReporter.js';
14
+ export declare class NoVoiceProvidersAvailableError extends Error {
15
+ readonly checkedEnvVars: string[];
16
+ constructor(checked: string[]);
17
+ }
18
+ export interface VoiceProviderEnvConfig {
19
+ /** Environment source. Defaults to process.env. */
20
+ env?: Record<string, string | undefined>;
21
+ /** Prefer streaming-class providers for first-try. Default true. */
22
+ preferStreaming?: boolean;
23
+ /** Language hint — providers whose capabilities don't match are still
24
+ * included (capability filtering is host-app policy), but this value
25
+ * is passed through to StreamingTTSConfig / StreamingSTTConfig via
26
+ * startSession consumers. */
27
+ languageHint?: string;
28
+ /** Target cost tier. Reserved for future per-session routing; not used yet. */
29
+ tier?: 'cheap' | 'standard' | 'premium';
30
+ /** Whether the STT chain keeps a ring buffer + re-routes mid-utterance.
31
+ * Default true — this is the whole point of the resilience work. */
32
+ enableMidUtteranceFailover?: boolean;
33
+ /** Whether the TTS chain re-sends accumulated tokens on primary
34
+ * failure. Default true. */
35
+ enableMidSynthesisFailover?: boolean;
36
+ }
37
+ export interface VoiceProviderBundle {
38
+ stt: StreamingSTTChain;
39
+ tts: StreamingTTSChain;
40
+ metrics: VoiceMetricsReporter;
41
+ breaker: CircuitBreaker;
42
+ /** Release any global resources the bundle owns. Currently a no-op
43
+ * because sessions clean up themselves; exposed now so host apps can
44
+ * depend on the shape. */
45
+ dispose(): Promise<void>;
46
+ }
47
+ export declare function createVoiceProvidersFromEnv(config?: VoiceProviderEnvConfig): VoiceProviderBundle;
48
+ //# sourceMappingURL=env-constructor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-constructor.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/env-constructor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAIjE,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE;CAO9B;AAED,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;kCAG8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IACxC;yEACqE;IACrE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC;iCAC6B;IAC7B,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,iBAAiB,CAAC;IACvB,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;IACxB;;+BAE2B;IAC3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,wBAAgB,2BAA2B,CACzC,MAAM,GAAE,sBAA2B,GAClC,mBAAmB,CA8ErB"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @module voice-pipeline/env-constructor
3
+ *
4
+ * Batteries-included constructor for `StreamingSTTChain` +
5
+ * `StreamingTTSChain`. Reads provider keys from an env-like object and
6
+ * builds priority-ordered chains with shared circuit breaker and metrics
7
+ * reporter. Host apps can skip the manual wiring and use this factory as
8
+ * the default integration point.
9
+ */
10
+ import { DeepgramStreamingSTT } from './providers/DeepgramStreamingSTT.js';
11
+ import { ElevenLabsStreamingSTT } from './providers/ElevenLabsStreamingSTT.js';
12
+ import { ElevenLabsStreamingTTS } from './providers/ElevenLabsStreamingTTS.js';
13
+ import { OpenAIRealtimeTTS } from './providers/OpenAIRealtimeTTS.js';
14
+ import { ElevenLabsBatchTTS } from './providers/ElevenLabsBatchTTS.js';
15
+ import { OpenAIBatchTTS } from './providers/OpenAIBatchTTS.js';
16
+ import { StreamingSTTChain } from './providers/StreamingSTTChain.js';
17
+ import { StreamingTTSChain } from './providers/StreamingTTSChain.js';
18
+ import { CircuitBreaker } from './CircuitBreaker.js';
19
+ import { VoiceMetricsReporter } from './VoiceMetricsReporter.js';
20
+ export class NoVoiceProvidersAvailableError extends Error {
21
+ constructor(checked) {
22
+ super(`No voice providers available. Set any of: ${checked.join(', ')} in the server env.`);
23
+ this.name = 'NoVoiceProvidersAvailableError';
24
+ this.checkedEnvVars = checked;
25
+ }
26
+ }
27
+ export function createVoiceProvidersFromEnv(config = {}) {
28
+ const env = config.env ?? globalThis.process?.env ?? {};
29
+ const checkedKeys = [
30
+ 'DEEPGRAM_API_KEY',
31
+ 'ELEVENLABS_API_KEY',
32
+ 'OPENAI_API_KEY',
33
+ ];
34
+ const deepgramKey = env['DEEPGRAM_API_KEY'];
35
+ const elevenLabsKey = env['ELEVENLABS_API_KEY'];
36
+ const openaiKey = env['OPENAI_API_KEY'];
37
+ const metrics = new VoiceMetricsReporter();
38
+ const breaker = new CircuitBreaker({
39
+ failureThreshold: 3,
40
+ windowMs: 60000,
41
+ cooldownMs: 60000,
42
+ });
43
+ const sttProviders = [];
44
+ if (deepgramKey) {
45
+ sttProviders.push(new DeepgramStreamingSTT({ apiKey: deepgramKey, priority: 10 }));
46
+ }
47
+ if (elevenLabsKey) {
48
+ sttProviders.push(new ElevenLabsStreamingSTT({ apiKey: elevenLabsKey, priority: 20 }));
49
+ }
50
+ const ttsProviders = [];
51
+ if (elevenLabsKey) {
52
+ ttsProviders.push(new ElevenLabsStreamingTTS({ apiKey: elevenLabsKey, priority: 10 }));
53
+ }
54
+ if (openaiKey) {
55
+ ttsProviders.push(new OpenAIRealtimeTTS({ apiKey: openaiKey, priority: 20 }));
56
+ ttsProviders.push(new OpenAIBatchTTS({ apiKey: openaiKey, priority: 90 }));
57
+ }
58
+ if (elevenLabsKey) {
59
+ ttsProviders.push(new ElevenLabsBatchTTS({ apiKey: elevenLabsKey, priority: 80 }));
60
+ }
61
+ if (sttProviders.length === 0 || ttsProviders.length === 0) {
62
+ throw new NoVoiceProvidersAvailableError(checkedKeys);
63
+ }
64
+ const stt = new StreamingSTTChain(sttProviders, {
65
+ breaker,
66
+ metrics,
67
+ enableMidUtteranceFailover: config.enableMidUtteranceFailover ?? true,
68
+ ringBufferCapacityMs: 3000,
69
+ });
70
+ const tts = new StreamingTTSChain(ttsProviders, {
71
+ breaker,
72
+ metrics,
73
+ enableMidSynthesisFailover: config.enableMidSynthesisFailover ?? true,
74
+ });
75
+ return {
76
+ stt,
77
+ tts,
78
+ metrics,
79
+ breaker,
80
+ async dispose() {
81
+ /* Sessions clean themselves up; nothing global to release today. */
82
+ },
83
+ };
84
+ }
85
+ //# sourceMappingURL=env-constructor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-constructor.js","sourceRoot":"","sources":["../../src/voice-pipeline/env-constructor.ts"],"names":[],"mappings":"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"}
@@ -104,5 +104,12 @@ export { WebSocketStreamTransport } from './WebSocketStreamTransport.js';
104
104
  export { WebRTCStreamTransport, createWebRTCTransport } from './WebRTCStreamTransport.js';
105
105
  export { VoicePipelineOrchestrator } from './VoicePipelineOrchestrator.js';
106
106
  export { VoiceInterruptError } from './VoiceInterruptError.js';
107
- export { DeepgramStreamingSTT, type DeepgramStreamingSTTConfig, ElevenLabsStreamingSTT, type ElevenLabsStreamingSTTConfig, ElevenLabsStreamingTTS, type ElevenLabsStreamingTTSConfig, AgentSessionVoiceAdapter, } from './providers/index.js';
107
+ export { DeepgramStreamingSTT, type DeepgramStreamingSTTConfig, ElevenLabsStreamingSTT, type ElevenLabsStreamingSTTConfig, ElevenLabsStreamingTTS, type ElevenLabsStreamingTTSConfig, AgentSessionVoiceAdapter, StreamingSTTChain, type StreamingSTTChainOptions, type ProviderSelectedEvent, type ProviderFailedEvent, type ProviderFailoverEvent, StreamingTTSChain, type StreamingTTSChainOptions, type TTSProviderSelectedEvent, type TTSProviderFailedEvent, type TTSProviderFailoverEvent, } from './providers/index.js';
108
+ export { VoicePipelineError, AggregateVoiceError, type HealthErrorClass, type VoicePipelineErrorInit, } from './VoicePipelineError.js';
109
+ export { type HealthyProvider, type ProviderCapabilities, type HealthCheckResult, defaultCapabilities, supportsLanguage, } from './HealthyProvider.js';
110
+ export { CircuitBreaker, type BreakerState, type CircuitBreakerOptions, type StateChangeEvent, } from './CircuitBreaker.js';
111
+ export { AudioRingBuffer, type AudioRingBufferOptions } from './AudioRingBuffer.js';
112
+ export { TranscriptDedupe, type TranscriptObservation, type DedupeResult, } from './TranscriptDedupe.js';
113
+ export { VoiceMetricsReporter, type VoiceMetricEvent, type VoiceMetricListener, } from './VoiceMetricsReporter.js';
114
+ export { createVoiceProvidersFromEnv, NoVoiceProvidersAvailableError, type VoiceProviderEnvConfig, type VoiceProviderBundle, } from './env-constructor.js';
108
115
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGG;AAIH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAG3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EACL,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,wBAAwB,GACzB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGG;AAIH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAG3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EACL,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,wBAAwB,EACxB,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAC9B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,GACzB,MAAM,sBAAsB,CAAC"}
@@ -113,5 +113,13 @@ export { VoicePipelineOrchestrator } from './VoicePipelineOrchestrator.js';
113
113
  // Typed error for barge-in interruptions
114
114
  export { VoiceInterruptError } from './VoiceInterruptError.js';
115
115
  // Streaming provider implementations
116
- export { DeepgramStreamingSTT, ElevenLabsStreamingSTT, ElevenLabsStreamingTTS, AgentSessionVoiceAdapter, } from './providers/index.js';
116
+ export { DeepgramStreamingSTT, ElevenLabsStreamingSTT, ElevenLabsStreamingTTS, AgentSessionVoiceAdapter, StreamingSTTChain, StreamingTTSChain, } from './providers/index.js';
117
+ // Resilience primitives
118
+ export { VoicePipelineError, AggregateVoiceError, } from './VoicePipelineError.js';
119
+ export { defaultCapabilities, supportsLanguage, } from './HealthyProvider.js';
120
+ export { CircuitBreaker, } from './CircuitBreaker.js';
121
+ export { AudioRingBuffer } from './AudioRingBuffer.js';
122
+ export { TranscriptDedupe, } from './TranscriptDedupe.js';
123
+ export { VoiceMetricsReporter, } from './VoiceMetricsReporter.js';
124
+ export { createVoiceProvidersFromEnv, NoVoiceProvidersAvailableError, } from './env-constructor.js';
117
125
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/voice-pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGG;AAEH,wDAAwD;AACxD,8EAA8E;AAC9E,cAAc,YAAY,CAAC;AAE3B,4CAA4C;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,6CAA6C;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,2CAA2C;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,oDAAoD;AACpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAE1F,gDAAgD;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,yCAAyC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qCAAqC;AACrC,OAAO,EACL,oBAAoB,EAEpB,sBAAsB,EAEtB,sBAAsB,EAEtB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/voice-pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGG;AAEH,wDAAwD;AACxD,8EAA8E;AAC9E,cAAc,YAAY,CAAC;AAE3B,4CAA4C;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,6CAA6C;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,2CAA2C;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,oDAAoD;AACpD,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAE1F,gDAAgD;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,yCAAyC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qCAAqC;AACrC,OAAO,EACL,oBAAoB,EAEpB,sBAAsB,EAEtB,sBAAsB,EAEtB,wBAAwB,EACxB,iBAAiB,EAKjB,iBAAiB,GAKlB,MAAM,sBAAsB,CAAC;AAE9B,wBAAwB;AACxB,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GAGpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAIL,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,cAAc,GAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAA+B,MAAM,sBAAsB,CAAC;AACpF,OAAO,EACL,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,GAGrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAG/B,MAAM,sBAAsB,CAAC"}
@@ -24,6 +24,16 @@
24
24
  * @see https://developers.deepgram.com/docs/streaming
25
25
  */
26
26
  import type { IStreamingSTT, StreamingSTTSession, StreamingSTTConfig } from '../types.js';
27
+ import { type HealthyProvider, type HealthCheckResult, type ProviderCapabilities } from '../HealthyProvider.js';
28
+ /**
29
+ * Shape of the injected health probe used for deterministic tests.
30
+ * Default implementation hits Deepgram's /v1/projects endpoint.
31
+ */
32
+ export type VoiceHealthProbe = (apiKey: string) => Promise<{
33
+ ok: boolean;
34
+ status: number;
35
+ latencyMs: number;
36
+ }>;
27
37
  /**
28
38
  * Configuration for the {@link DeepgramStreamingSTT} provider.
29
39
  */
@@ -40,6 +50,15 @@ export interface DeepgramStreamingSTTConfig {
40
50
  * @default 'nova-2'
41
51
  */
42
52
  model?: string;
53
+ /**
54
+ * Chain priority. Lower values are tried first.
55
+ * @default 10
56
+ */
57
+ priority?: number;
58
+ /** Optional capability overrides. Merged into defaultCapabilities(). */
59
+ capabilities?: Partial<ProviderCapabilities>;
60
+ /** Injectable health probe for tests. Defaults to Deepgram /v1/projects. */
61
+ healthProbe?: VoiceHealthProbe;
43
62
  }
44
63
  /**
45
64
  * Streaming STT provider that creates Deepgram WebSocket sessions.
@@ -55,12 +74,16 @@ export interface DeepgramStreamingSTTConfig {
55
74
  * session.on('transcript', (event) => console.log(event.text));
56
75
  * ```
57
76
  */
58
- export declare class DeepgramStreamingSTT implements IStreamingSTT {
77
+ export declare class DeepgramStreamingSTT implements IStreamingSTT, HealthyProvider {
59
78
  private readonly config;
60
79
  readonly providerId = "deepgram-streaming";
61
80
  readonly isStreaming = true;
81
+ readonly priority: number;
82
+ readonly capabilities: ProviderCapabilities;
62
83
  private readonly keyPool;
84
+ private readonly healthProbe;
63
85
  constructor(config: DeepgramStreamingSTTConfig);
86
+ healthCheck(): Promise<HealthCheckResult>;
64
87
  /**
65
88
  * Create a new streaming STT session connected to Deepgram.
66
89
  * Each session gets a fresh key from the round-robin pool.
@@ -1 +1 @@
1
- {"version":3,"file":"DeepgramStreamingSTT.d.ts","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/DeepgramStreamingSTT.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAInB,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmQD;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAqB,YAAW,aAAa;IAK5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,UAAU,wBAAwB;IAC3C,QAAQ,CAAC,WAAW,QAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;gBAER,MAAM,EAAE,0BAA0B;IAI/D;;;OAGG;IACG,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAM9E"}
1
+ {"version":3,"file":"DeepgramStreamingSTT.d.ts","sourceRoot":"","sources":["../../../src/voice-pipeline/providers/DeepgramStreamingSTT.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAInB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAC;AAG/B;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,MAAM,KACX,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAmBjE;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAE7C,4EAA4E;IAC5E,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAmQD;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAqB,YAAW,aAAa,EAAE,eAAe;IAQ7D,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,QAAQ,CAAC,UAAU,wBAAwB;IAC3C,QAAQ,CAAC,WAAW,QAAQ;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;gBAElB,MAAM,EAAE,0BAA0B;IAazD,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA6B/C;;;OAGG;IACG,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAM9E"}
@@ -26,6 +26,21 @@
26
26
  import { EventEmitter } from 'node:events';
27
27
  import WebSocket from 'ws';
28
28
  import { ApiKeyPool } from '../../core/providers/ApiKeyPool.js';
29
+ import { defaultCapabilities, } from '../HealthyProvider.js';
30
+ import { VoicePipelineError } from '../VoicePipelineError.js';
31
+ async function defaultDeepgramProbe(apiKey) {
32
+ const start = Date.now();
33
+ try {
34
+ const res = await fetch('https://api.deepgram.com/v1/projects', {
35
+ headers: { Authorization: `Token ${apiKey}` },
36
+ signal: AbortSignal.timeout(1000),
37
+ });
38
+ return { ok: res.ok, status: res.status, latencyMs: Date.now() - start };
39
+ }
40
+ catch (err) {
41
+ throw err;
42
+ }
43
+ }
29
44
  // ---------------------------------------------------------------------------
30
45
  // Session Implementation
31
46
  // ---------------------------------------------------------------------------
@@ -229,6 +244,42 @@ export class DeepgramStreamingSTT {
229
244
  this.providerId = 'deepgram-streaming';
230
245
  this.isStreaming = true;
231
246
  this.keyPool = new ApiKeyPool(config.apiKey);
247
+ this.priority = config.priority ?? 10;
248
+ this.capabilities = defaultCapabilities({
249
+ languages: ['*'],
250
+ streaming: true,
251
+ costTier: 'standard',
252
+ latencyClass: 'realtime',
253
+ ...(config.capabilities ?? {}),
254
+ });
255
+ this.healthProbe = config.healthProbe ?? defaultDeepgramProbe;
256
+ }
257
+ async healthCheck() {
258
+ if (!this.keyPool.hasKeys) {
259
+ return { ok: false, error: { class: 'auth', message: 'no api key available' } };
260
+ }
261
+ const key = this.keyPool.next();
262
+ try {
263
+ const res = await this.healthProbe(key);
264
+ if (res.ok)
265
+ return { ok: true, latencyMs: res.latencyMs };
266
+ const classified = VoicePipelineError.classifyError(new Error(`HTTP ${res.status}`), { kind: 'stt', provider: this.providerId });
267
+ return {
268
+ ok: false,
269
+ latencyMs: res.latencyMs,
270
+ error: { class: classified.errorClass, message: `HTTP ${res.status}` },
271
+ };
272
+ }
273
+ catch (err) {
274
+ const classified = VoicePipelineError.classifyError(err, {
275
+ kind: 'stt',
276
+ provider: this.providerId,
277
+ });
278
+ return {
279
+ ok: false,
280
+ error: { class: classified.errorClass, message: classified.message },
281
+ };
282
+ }
232
283
  }
233
284
  /**
234
285
  * Create a new streaming STT session connected to Deepgram.