@sudocode-ai/local-server 0.1.16 → 0.1.18-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/better-sqlite3-loader.d.ts +9 -0
- package/dist/better-sqlite3-loader.d.ts.map +1 -0
- package/dist/better-sqlite3-loader.js +24 -0
- package/dist/better-sqlite3-loader.js.map +1 -0
- package/dist/execution/executors/agent-executor-wrapper.d.ts +6 -0
- package/dist/execution/executors/agent-executor-wrapper.d.ts.map +1 -1
- package/dist/execution/executors/agent-executor-wrapper.js +75 -4
- package/dist/execution/executors/agent-executor-wrapper.js.map +1 -1
- package/dist/execution/executors/executor-factory.d.ts +9 -6
- package/dist/execution/executors/executor-factory.d.ts.map +1 -1
- package/dist/execution/executors/executor-factory.js +6 -5
- package/dist/execution/executors/executor-factory.js.map +1 -1
- package/dist/execution/worktree/config.js +1 -1
- package/dist/execution/worktree/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/public/assets/index-B1p5HV93.css +1 -0
- package/dist/public/assets/index-qqIsBBjJ.js +3836 -0
- package/dist/public/assets/index-qqIsBBjJ.js.map +1 -0
- package/dist/public/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm +0 -0
- package/dist/public/index.html +2 -2
- package/dist/public/kokoro-test.html +197 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +39 -0
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/executions.d.ts.map +1 -1
- package/dist/routes/executions.js +9 -0
- package/dist/routes/executions.js.map +1 -1
- package/dist/routes/voice.d.ts +12 -0
- package/dist/routes/voice.d.ts.map +1 -0
- package/dist/routes/voice.js +387 -0
- package/dist/routes/voice.js.map +1 -0
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/routes/workflows.js +2 -1
- package/dist/routes/workflows.js.map +1 -1
- package/dist/services/db.d.ts +1 -1
- package/dist/services/db.d.ts.map +1 -1
- package/dist/services/db.js +2 -2
- package/dist/services/db.js.map +1 -1
- package/dist/services/execution-service.d.ts +8 -0
- package/dist/services/execution-service.d.ts.map +1 -1
- package/dist/services/execution-service.js +27 -5
- package/dist/services/execution-service.js.map +1 -1
- package/dist/services/narration-service.d.ts +304 -0
- package/dist/services/narration-service.d.ts.map +1 -0
- package/dist/services/narration-service.js +729 -0
- package/dist/services/narration-service.js.map +1 -0
- package/dist/services/stt-providers/index.d.ts +21 -0
- package/dist/services/stt-providers/index.d.ts.map +1 -0
- package/dist/services/stt-providers/index.js +32 -0
- package/dist/services/stt-providers/index.js.map +1 -0
- package/dist/services/stt-providers/openai-whisper.d.ts +66 -0
- package/dist/services/stt-providers/openai-whisper.d.ts.map +1 -0
- package/dist/services/stt-providers/openai-whisper.js +137 -0
- package/dist/services/stt-providers/openai-whisper.js.map +1 -0
- package/dist/services/stt-providers/whisper-local.d.ts +64 -0
- package/dist/services/stt-providers/whisper-local.d.ts.map +1 -0
- package/dist/services/stt-providers/whisper-local.js +166 -0
- package/dist/services/stt-providers/whisper-local.js.map +1 -0
- package/dist/services/stt-service.d.ts +160 -0
- package/dist/services/stt-service.d.ts.map +1 -0
- package/dist/services/stt-service.js +246 -0
- package/dist/services/stt-service.js.map +1 -0
- package/dist/services/tts-providers/browser-tts.d.ts +64 -0
- package/dist/services/tts-providers/browser-tts.d.ts.map +1 -0
- package/dist/services/tts-providers/browser-tts.js +89 -0
- package/dist/services/tts-providers/browser-tts.js.map +1 -0
- package/dist/services/tts-providers/index.d.ts +20 -0
- package/dist/services/tts-providers/index.d.ts.map +1 -0
- package/dist/services/tts-providers/index.js +31 -0
- package/dist/services/tts-providers/index.js.map +1 -0
- package/dist/services/tts-service.d.ts +190 -0
- package/dist/services/tts-service.d.ts.map +1 -0
- package/dist/services/tts-service.js +296 -0
- package/dist/services/tts-service.js.map +1 -0
- package/dist/services/tts-sidecar-manager.d.ts +276 -0
- package/dist/services/tts-sidecar-manager.d.ts.map +1 -0
- package/dist/services/tts-sidecar-manager.js +665 -0
- package/dist/services/tts-sidecar-manager.js.map +1 -0
- package/dist/services/websocket.d.ts +31 -1
- package/dist/services/websocket.d.ts.map +1 -1
- package/dist/services/websocket.js +149 -0
- package/dist/services/websocket.js.map +1 -1
- package/dist/services/worktree-sync-service.d.ts +17 -2
- package/dist/services/worktree-sync-service.d.ts.map +1 -1
- package/dist/services/worktree-sync-service.js +103 -6
- package/dist/services/worktree-sync-service.js.map +1 -1
- package/dist/utils/voice-config.d.ts +26 -0
- package/dist/utils/voice-config.d.ts.map +1 -0
- package/dist/utils/voice-config.js +48 -0
- package/dist/utils/voice-config.js.map +1 -0
- package/dist/workers/execution-worker.js +12 -4
- package/dist/workers/execution-worker.js.map +1 -1
- package/dist/workflow/base-workflow-engine.d.ts +3 -1
- package/dist/workflow/base-workflow-engine.d.ts.map +1 -1
- package/dist/workflow/base-workflow-engine.js.map +1 -1
- package/dist/workflow/engines/orchestrator-engine.d.ts +5 -1
- package/dist/workflow/engines/orchestrator-engine.d.ts.map +1 -1
- package/dist/workflow/engines/orchestrator-engine.js +4 -1
- package/dist/workflow/engines/orchestrator-engine.js.map +1 -1
- package/dist/workflow/engines/sequential-engine.d.ts +9 -2
- package/dist/workflow/engines/sequential-engine.d.ts.map +1 -1
- package/dist/workflow/engines/sequential-engine.js +102 -22
- package/dist/workflow/engines/sequential-engine.js.map +1 -1
- package/dist/workflow/workflow-engine.d.ts +8 -1
- package/dist/workflow/workflow-engine.d.ts.map +1 -1
- package/package.json +13 -4
- package/dist/public/assets/index-D4AKx6EO.css +0 -1
- package/dist/public/assets/index-DorQqwGV.js +0 -927
- package/dist/public/assets/index-DorQqwGV.js.map +0 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Speech Service
|
|
3
|
+
*
|
|
4
|
+
* Provides a pluggable TTS abstraction with multiple provider support.
|
|
5
|
+
* Handles provider selection, fallback, voice listing, and availability checking.
|
|
6
|
+
*/
|
|
7
|
+
import type { TTSProvider as TTSProviderType, TTSProviderOptions, TTSProviderResult, TTSVoice } from "@sudocode-ai/types/voice";
|
|
8
|
+
/**
|
|
9
|
+
* Interface for TTS providers
|
|
10
|
+
*/
|
|
11
|
+
export interface TTSProvider {
|
|
12
|
+
/** Provider identifier */
|
|
13
|
+
readonly id: TTSProviderType;
|
|
14
|
+
/** Human-readable provider name */
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/**
|
|
17
|
+
* Synthesize text to speech
|
|
18
|
+
*
|
|
19
|
+
* @param text - Text to synthesize
|
|
20
|
+
* @param options - Optional synthesis options
|
|
21
|
+
* @returns Promise resolving to synthesis result
|
|
22
|
+
*/
|
|
23
|
+
synthesize(text: string, options?: TTSProviderOptions): Promise<TTSProviderResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if this provider is currently available
|
|
26
|
+
* (e.g., service is running, API key is configured)
|
|
27
|
+
*
|
|
28
|
+
* @returns Promise resolving to true if provider is available
|
|
29
|
+
*/
|
|
30
|
+
isAvailable(): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Get available voices for this provider
|
|
33
|
+
* Optional - not all providers support voice listing
|
|
34
|
+
*
|
|
35
|
+
* @returns Promise resolving to array of available voices
|
|
36
|
+
*/
|
|
37
|
+
getVoices?(): Promise<TTSVoice[]>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Configuration for the TTS service
|
|
41
|
+
*/
|
|
42
|
+
export interface TTSServiceConfig {
|
|
43
|
+
/** Default provider to use when none specified */
|
|
44
|
+
defaultProvider: TTSProviderType;
|
|
45
|
+
/** Kokoro server URL for local TTS */
|
|
46
|
+
kokoroUrl: string;
|
|
47
|
+
/** Default voice to use */
|
|
48
|
+
defaultVoice: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get TTS configuration from voice settings config.
|
|
52
|
+
*
|
|
53
|
+
* @param voiceConfig - Optional voice settings from project config.json
|
|
54
|
+
*/
|
|
55
|
+
export declare function getTTSConfig(voiceConfig?: {
|
|
56
|
+
tts?: {
|
|
57
|
+
provider?: TTSProviderType;
|
|
58
|
+
kokoroUrl?: string;
|
|
59
|
+
defaultVoice?: string;
|
|
60
|
+
};
|
|
61
|
+
}): TTSServiceConfig;
|
|
62
|
+
/**
|
|
63
|
+
* Error thrown when no TTS providers are available
|
|
64
|
+
*/
|
|
65
|
+
export declare class NoTTSProviderError extends Error {
|
|
66
|
+
constructor();
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Error thrown when a specific provider is not found
|
|
70
|
+
*/
|
|
71
|
+
export declare class TTSProviderNotFoundError extends Error {
|
|
72
|
+
constructor(providerName: string);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Error thrown when synthesis fails
|
|
76
|
+
*/
|
|
77
|
+
export declare class SynthesisError extends Error {
|
|
78
|
+
readonly provider: string;
|
|
79
|
+
readonly cause?: Error | undefined;
|
|
80
|
+
constructor(message: string, provider: string, cause?: Error | undefined);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Text-to-Speech Service
|
|
84
|
+
*
|
|
85
|
+
* Manages multiple TTS providers with automatic fallback support.
|
|
86
|
+
*/
|
|
87
|
+
export declare class TTSService {
|
|
88
|
+
private providers;
|
|
89
|
+
private config;
|
|
90
|
+
private availabilityCache;
|
|
91
|
+
private availabilityCacheTime;
|
|
92
|
+
private readonly CACHE_TTL_MS;
|
|
93
|
+
constructor(config?: Partial<TTSServiceConfig>);
|
|
94
|
+
/**
|
|
95
|
+
* Register a TTS provider
|
|
96
|
+
*
|
|
97
|
+
* @param provider - The provider to register
|
|
98
|
+
*/
|
|
99
|
+
registerProvider(provider: TTSProvider): void;
|
|
100
|
+
/**
|
|
101
|
+
* Unregister a TTS provider
|
|
102
|
+
*
|
|
103
|
+
* @param providerId - ID of the provider to unregister
|
|
104
|
+
*/
|
|
105
|
+
unregisterProvider(providerId: TTSProviderType): void;
|
|
106
|
+
/**
|
|
107
|
+
* Get a provider by ID
|
|
108
|
+
*
|
|
109
|
+
* @param providerId - ID of the provider
|
|
110
|
+
* @returns The provider if found
|
|
111
|
+
*/
|
|
112
|
+
getProvider(providerId: TTSProviderType): TTSProvider | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Check if a provider's availability is cached and still valid
|
|
115
|
+
*/
|
|
116
|
+
private isCacheValid;
|
|
117
|
+
/**
|
|
118
|
+
* Check if a provider is available (with caching)
|
|
119
|
+
*
|
|
120
|
+
* @param providerId - ID of the provider to check
|
|
121
|
+
* @returns Promise resolving to true if available
|
|
122
|
+
*/
|
|
123
|
+
isProviderAvailable(providerId: TTSProviderType): Promise<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* Get all available providers (those that are registered and currently available)
|
|
126
|
+
*
|
|
127
|
+
* @returns Promise resolving to array of available provider IDs
|
|
128
|
+
*/
|
|
129
|
+
getAvailableProviders(): Promise<TTSProviderType[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Get all registered provider IDs
|
|
132
|
+
*
|
|
133
|
+
* @returns Array of registered provider IDs
|
|
134
|
+
*/
|
|
135
|
+
getRegisteredProviders(): TTSProviderType[];
|
|
136
|
+
/**
|
|
137
|
+
* Get the default provider ID from configuration
|
|
138
|
+
*
|
|
139
|
+
* @returns The default provider ID
|
|
140
|
+
*/
|
|
141
|
+
getDefaultProvider(): TTSProviderType;
|
|
142
|
+
/**
|
|
143
|
+
* Get the configuration
|
|
144
|
+
*
|
|
145
|
+
* @returns The current configuration
|
|
146
|
+
*/
|
|
147
|
+
getConfig(): TTSServiceConfig;
|
|
148
|
+
/**
|
|
149
|
+
* Clear the availability cache
|
|
150
|
+
*/
|
|
151
|
+
clearAvailabilityCache(): void;
|
|
152
|
+
/**
|
|
153
|
+
* Get all available voices across all available providers
|
|
154
|
+
*
|
|
155
|
+
* @returns Promise resolving to array of voices from all providers
|
|
156
|
+
*/
|
|
157
|
+
getAllVoices(): Promise<TTSVoice[]>;
|
|
158
|
+
/**
|
|
159
|
+
* Get voices for a specific provider
|
|
160
|
+
*
|
|
161
|
+
* @param providerId - ID of the provider
|
|
162
|
+
* @returns Promise resolving to array of voices
|
|
163
|
+
*/
|
|
164
|
+
getVoicesForProvider(providerId: TTSProviderType): Promise<TTSVoice[]>;
|
|
165
|
+
/**
|
|
166
|
+
* Synthesize text using the specified or default provider
|
|
167
|
+
*
|
|
168
|
+
* Falls back to other available providers if the preferred one fails.
|
|
169
|
+
*
|
|
170
|
+
* @param text - Text to synthesize
|
|
171
|
+
* @param options - Optional synthesis options
|
|
172
|
+
* @param preferredProvider - Preferred provider ID (uses default if not specified)
|
|
173
|
+
* @returns Promise resolving to synthesis result
|
|
174
|
+
* @throws {NoTTSProviderError} If no providers are available
|
|
175
|
+
* @throws {SynthesisError} If synthesis fails on all providers
|
|
176
|
+
*/
|
|
177
|
+
synthesize(text: string, options?: TTSProviderOptions, preferredProvider?: TTSProviderType): Promise<TTSProviderResult>;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get or create the global TTS service instance
|
|
181
|
+
*
|
|
182
|
+
* @param config - Optional configuration override
|
|
183
|
+
* @returns The TTS service instance
|
|
184
|
+
*/
|
|
185
|
+
export declare function getTTSService(config?: Partial<TTSServiceConfig>): TTSService;
|
|
186
|
+
/**
|
|
187
|
+
* Reset the global TTS service instance (for testing)
|
|
188
|
+
*/
|
|
189
|
+
export declare function resetTTSService(): void;
|
|
190
|
+
//# sourceMappingURL=tts-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-service.d.ts","sourceRoot":"","sources":["../../src/services/tts-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Speech Service
|
|
3
|
+
*
|
|
4
|
+
* Provides a pluggable TTS abstraction with multiple provider support.
|
|
5
|
+
* Handles provider selection, fallback, voice listing, and availability checking.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Default TTS configuration values
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_TTS_CONFIG = {
|
|
11
|
+
defaultProvider: "browser",
|
|
12
|
+
kokoroUrl: "http://localhost:8880/v1",
|
|
13
|
+
defaultVoice: "nova",
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Get TTS configuration from voice settings config.
|
|
17
|
+
*
|
|
18
|
+
* @param voiceConfig - Optional voice settings from project config.json
|
|
19
|
+
*/
|
|
20
|
+
export function getTTSConfig(voiceConfig) {
|
|
21
|
+
return {
|
|
22
|
+
defaultProvider: voiceConfig?.tts?.provider || DEFAULT_TTS_CONFIG.defaultProvider,
|
|
23
|
+
kokoroUrl: voiceConfig?.tts?.kokoroUrl || DEFAULT_TTS_CONFIG.kokoroUrl,
|
|
24
|
+
defaultVoice: voiceConfig?.tts?.defaultVoice || DEFAULT_TTS_CONFIG.defaultVoice,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Error thrown when no TTS providers are available
|
|
29
|
+
*/
|
|
30
|
+
export class NoTTSProviderError extends Error {
|
|
31
|
+
constructor() {
|
|
32
|
+
super("No TTS providers are available");
|
|
33
|
+
this.name = "NoTTSProviderError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Error thrown when a specific provider is not found
|
|
38
|
+
*/
|
|
39
|
+
export class TTSProviderNotFoundError extends Error {
|
|
40
|
+
constructor(providerName) {
|
|
41
|
+
super(`TTS provider '${providerName}' not found`);
|
|
42
|
+
this.name = "TTSProviderNotFoundError";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Error thrown when synthesis fails
|
|
47
|
+
*/
|
|
48
|
+
export class SynthesisError extends Error {
|
|
49
|
+
provider;
|
|
50
|
+
cause;
|
|
51
|
+
constructor(message, provider, cause) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.provider = provider;
|
|
54
|
+
this.cause = cause;
|
|
55
|
+
this.name = "SynthesisError";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Text-to-Speech Service
|
|
60
|
+
*
|
|
61
|
+
* Manages multiple TTS providers with automatic fallback support.
|
|
62
|
+
*/
|
|
63
|
+
export class TTSService {
|
|
64
|
+
providers = new Map();
|
|
65
|
+
config;
|
|
66
|
+
availabilityCache = new Map();
|
|
67
|
+
availabilityCacheTime = new Map();
|
|
68
|
+
CACHE_TTL_MS = 30000; // 30 seconds
|
|
69
|
+
constructor(config) {
|
|
70
|
+
this.config = { ...getTTSConfig(), ...config };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Register a TTS provider
|
|
74
|
+
*
|
|
75
|
+
* @param provider - The provider to register
|
|
76
|
+
*/
|
|
77
|
+
registerProvider(provider) {
|
|
78
|
+
this.providers.set(provider.id, provider);
|
|
79
|
+
// Invalidate availability cache when a new provider is registered
|
|
80
|
+
this.availabilityCache.delete(provider.id);
|
|
81
|
+
this.availabilityCacheTime.delete(provider.id);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Unregister a TTS provider
|
|
85
|
+
*
|
|
86
|
+
* @param providerId - ID of the provider to unregister
|
|
87
|
+
*/
|
|
88
|
+
unregisterProvider(providerId) {
|
|
89
|
+
this.providers.delete(providerId);
|
|
90
|
+
this.availabilityCache.delete(providerId);
|
|
91
|
+
this.availabilityCacheTime.delete(providerId);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get a provider by ID
|
|
95
|
+
*
|
|
96
|
+
* @param providerId - ID of the provider
|
|
97
|
+
* @returns The provider if found
|
|
98
|
+
*/
|
|
99
|
+
getProvider(providerId) {
|
|
100
|
+
return this.providers.get(providerId);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if a provider's availability is cached and still valid
|
|
104
|
+
*/
|
|
105
|
+
isCacheValid(providerId) {
|
|
106
|
+
const cacheTime = this.availabilityCacheTime.get(providerId);
|
|
107
|
+
if (!cacheTime)
|
|
108
|
+
return false;
|
|
109
|
+
return Date.now() - cacheTime < this.CACHE_TTL_MS;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if a provider is available (with caching)
|
|
113
|
+
*
|
|
114
|
+
* @param providerId - ID of the provider to check
|
|
115
|
+
* @returns Promise resolving to true if available
|
|
116
|
+
*/
|
|
117
|
+
async isProviderAvailable(providerId) {
|
|
118
|
+
const provider = this.providers.get(providerId);
|
|
119
|
+
if (!provider)
|
|
120
|
+
return false;
|
|
121
|
+
// Check cache first
|
|
122
|
+
if (this.isCacheValid(providerId)) {
|
|
123
|
+
return this.availabilityCache.get(providerId) ?? false;
|
|
124
|
+
}
|
|
125
|
+
// Check actual availability
|
|
126
|
+
try {
|
|
127
|
+
const available = await provider.isAvailable();
|
|
128
|
+
this.availabilityCache.set(providerId, available);
|
|
129
|
+
this.availabilityCacheTime.set(providerId, Date.now());
|
|
130
|
+
return available;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
this.availabilityCache.set(providerId, false);
|
|
134
|
+
this.availabilityCacheTime.set(providerId, Date.now());
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get all available providers (those that are registered and currently available)
|
|
140
|
+
*
|
|
141
|
+
* @returns Promise resolving to array of available provider IDs
|
|
142
|
+
*/
|
|
143
|
+
async getAvailableProviders() {
|
|
144
|
+
const availableProviders = [];
|
|
145
|
+
for (const providerId of this.providers.keys()) {
|
|
146
|
+
if (await this.isProviderAvailable(providerId)) {
|
|
147
|
+
availableProviders.push(providerId);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return availableProviders;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get all registered provider IDs
|
|
154
|
+
*
|
|
155
|
+
* @returns Array of registered provider IDs
|
|
156
|
+
*/
|
|
157
|
+
getRegisteredProviders() {
|
|
158
|
+
return Array.from(this.providers.keys());
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get the default provider ID from configuration
|
|
162
|
+
*
|
|
163
|
+
* @returns The default provider ID
|
|
164
|
+
*/
|
|
165
|
+
getDefaultProvider() {
|
|
166
|
+
return this.config.defaultProvider;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get the configuration
|
|
170
|
+
*
|
|
171
|
+
* @returns The current configuration
|
|
172
|
+
*/
|
|
173
|
+
getConfig() {
|
|
174
|
+
return { ...this.config };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Clear the availability cache
|
|
178
|
+
*/
|
|
179
|
+
clearAvailabilityCache() {
|
|
180
|
+
this.availabilityCache.clear();
|
|
181
|
+
this.availabilityCacheTime.clear();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get all available voices across all available providers
|
|
185
|
+
*
|
|
186
|
+
* @returns Promise resolving to array of voices from all providers
|
|
187
|
+
*/
|
|
188
|
+
async getAllVoices() {
|
|
189
|
+
const allVoices = [];
|
|
190
|
+
for (const [providerId, provider] of this.providers) {
|
|
191
|
+
if (!(await this.isProviderAvailable(providerId))) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (provider.getVoices) {
|
|
195
|
+
try {
|
|
196
|
+
const voices = await provider.getVoices();
|
|
197
|
+
allVoices.push(...voices);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// If voice listing fails, skip this provider
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return allVoices;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get voices for a specific provider
|
|
208
|
+
*
|
|
209
|
+
* @param providerId - ID of the provider
|
|
210
|
+
* @returns Promise resolving to array of voices
|
|
211
|
+
*/
|
|
212
|
+
async getVoicesForProvider(providerId) {
|
|
213
|
+
const provider = this.providers.get(providerId);
|
|
214
|
+
if (!provider) {
|
|
215
|
+
throw new TTSProviderNotFoundError(providerId);
|
|
216
|
+
}
|
|
217
|
+
if (!provider.getVoices) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
return provider.getVoices();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Synthesize text using the specified or default provider
|
|
224
|
+
*
|
|
225
|
+
* Falls back to other available providers if the preferred one fails.
|
|
226
|
+
*
|
|
227
|
+
* @param text - Text to synthesize
|
|
228
|
+
* @param options - Optional synthesis options
|
|
229
|
+
* @param preferredProvider - Preferred provider ID (uses default if not specified)
|
|
230
|
+
* @returns Promise resolving to synthesis result
|
|
231
|
+
* @throws {NoTTSProviderError} If no providers are available
|
|
232
|
+
* @throws {SynthesisError} If synthesis fails on all providers
|
|
233
|
+
*/
|
|
234
|
+
async synthesize(text, options, preferredProvider) {
|
|
235
|
+
const providerToUse = preferredProvider || this.config.defaultProvider;
|
|
236
|
+
// Build provider order: preferred first, then others
|
|
237
|
+
const providerOrder = [providerToUse];
|
|
238
|
+
for (const providerId of this.providers.keys()) {
|
|
239
|
+
if (providerId !== providerToUse) {
|
|
240
|
+
providerOrder.push(providerId);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const errors = [];
|
|
244
|
+
for (const providerId of providerOrder) {
|
|
245
|
+
const provider = this.providers.get(providerId);
|
|
246
|
+
if (!provider)
|
|
247
|
+
continue;
|
|
248
|
+
// Check availability
|
|
249
|
+
if (!(await this.isProviderAvailable(providerId))) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
const result = await provider.synthesize(text, options);
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
258
|
+
errors.push({ provider: providerId, error: err });
|
|
259
|
+
// Invalidate cache for this provider since it failed
|
|
260
|
+
this.availabilityCache.delete(providerId);
|
|
261
|
+
this.availabilityCacheTime.delete(providerId);
|
|
262
|
+
// Continue to next provider
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// If we get here, all providers failed
|
|
266
|
+
if (errors.length === 0) {
|
|
267
|
+
throw new NoTTSProviderError();
|
|
268
|
+
}
|
|
269
|
+
const lastError = errors[errors.length - 1];
|
|
270
|
+
throw new SynthesisError(`Synthesis failed on all providers. Last error: ${lastError.error.message}`, lastError.provider, lastError.error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Global TTS service instance
|
|
275
|
+
* Lazy-initialized on first use
|
|
276
|
+
*/
|
|
277
|
+
let ttsServiceInstance = null;
|
|
278
|
+
/**
|
|
279
|
+
* Get or create the global TTS service instance
|
|
280
|
+
*
|
|
281
|
+
* @param config - Optional configuration override
|
|
282
|
+
* @returns The TTS service instance
|
|
283
|
+
*/
|
|
284
|
+
export function getTTSService(config) {
|
|
285
|
+
if (!ttsServiceInstance) {
|
|
286
|
+
ttsServiceInstance = new TTSService(config);
|
|
287
|
+
}
|
|
288
|
+
return ttsServiceInstance;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Reset the global TTS service instance (for testing)
|
|
292
|
+
*/
|
|
293
|
+
export function resetTTSService() {
|
|
294
|
+
ttsServiceInstance = null;
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=tts-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-service.js","sourceRoot":"","sources":["../../src/services/tts-service.ts"],"names":[],"mappings":"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"}
|