@zhoujinandrew/fish-audio-mcp-server 0.7.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/LICENSE +21 -0
- package/README.md +430 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/services/fishAudioSDK.d.ts +29 -0
- package/dist/services/fishAudioSDK.d.ts.map +1 -0
- package/dist/services/fishAudioSDK.js +185 -0
- package/dist/services/fishAudioSDK.js.map +1 -0
- package/dist/tools/listReferences.d.ts +22 -0
- package/dist/tools/listReferences.d.ts.map +1 -0
- package/dist/tools/listReferences.js +40 -0
- package/dist/tools/listReferences.js.map +1 -0
- package/dist/tools/tts.d.ts +100 -0
- package/dist/tools/tts.d.ts.map +1 -0
- package/dist/tools/tts.js +328 -0
- package/dist/tools/tts.js.map +1 -0
- package/dist/types/index.d.ts +98 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +20 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/audioPlayer.d.ts +3 -0
- package/dist/utils/audioPlayer.d.ts.map +1 -0
- package/dist/utils/audioPlayer.js +35 -0
- package/dist/utils/audioPlayer.js.map +1 -0
- package/dist/utils/config.d.ts +4 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +119 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/realTimePlayer.d.ts +13 -0
- package/dist/utils/realTimePlayer.d.ts.map +1 -0
- package/dist/utils/realTimePlayer.js +92 -0
- package/dist/utils/realTimePlayer.js.map +1 -0
- package/dist/utils/referenceSelector.d.ts +35 -0
- package/dist/utils/referenceSelector.d.ts.map +1 -0
- package/dist/utils/referenceSelector.js +72 -0
- package/dist/utils/referenceSelector.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { FishAudioSDKService } from '../services/fishAudioSDK.js';
|
|
2
|
+
import { FishAudioError } from '../types/index.js';
|
|
3
|
+
import { loadConfig, getOutputPath } from '../utils/config.js';
|
|
4
|
+
import { writeFileSync, createWriteStream } from 'fs';
|
|
5
|
+
import { playAudio, isAudioPlaybackSupported } from '../utils/audioPlayer.js';
|
|
6
|
+
import { RealTimeAudioPlayer } from '../utils/realTimePlayer.js';
|
|
7
|
+
import { ReferenceSelector } from '../utils/referenceSelector.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
export class TTSTool {
|
|
10
|
+
name = 'fish_audio_tts';
|
|
11
|
+
description = 'Generate speech from text using Fish Audio TTS API';
|
|
12
|
+
inputSchema = {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
text: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Text to convert to speech',
|
|
18
|
+
maxLength: 10000
|
|
19
|
+
},
|
|
20
|
+
reference_id: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'Voice model reference ID (optional)'
|
|
23
|
+
},
|
|
24
|
+
reference_name: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Voice model name to search for (optional)'
|
|
27
|
+
},
|
|
28
|
+
reference_tag: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'Voice model tag to search for (optional)'
|
|
31
|
+
},
|
|
32
|
+
streaming: {
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
description: 'Enable HTTP streaming mode (optional)',
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
37
|
+
websocket_streaming: {
|
|
38
|
+
type: 'boolean',
|
|
39
|
+
description: 'Enable WebSocket streaming mode (optional)',
|
|
40
|
+
default: false
|
|
41
|
+
},
|
|
42
|
+
realtime_play: {
|
|
43
|
+
type: 'boolean',
|
|
44
|
+
description: 'Enable real-time audio playback during streaming (optional)',
|
|
45
|
+
default: false
|
|
46
|
+
},
|
|
47
|
+
format: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
enum: ['mp3', 'wav', 'pcm', 'opus'],
|
|
50
|
+
description: 'Output audio format (optional)',
|
|
51
|
+
default: 'mp3'
|
|
52
|
+
},
|
|
53
|
+
mp3_bitrate: {
|
|
54
|
+
type: 'number',
|
|
55
|
+
enum: [64, 128, 192],
|
|
56
|
+
description: 'MP3 bitrate in kbps (optional)',
|
|
57
|
+
default: 128
|
|
58
|
+
},
|
|
59
|
+
normalize: {
|
|
60
|
+
type: 'boolean',
|
|
61
|
+
description: 'Enable text normalization (optional)',
|
|
62
|
+
default: true
|
|
63
|
+
},
|
|
64
|
+
latency: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
enum: ['normal', 'balanced'],
|
|
67
|
+
description: 'Latency mode (optional)',
|
|
68
|
+
default: 'balanced'
|
|
69
|
+
},
|
|
70
|
+
output_path: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
description: 'Custom output file path (optional)'
|
|
73
|
+
},
|
|
74
|
+
auto_play: {
|
|
75
|
+
type: 'boolean',
|
|
76
|
+
description: 'Automatically play the generated audio (optional)',
|
|
77
|
+
default: false
|
|
78
|
+
},
|
|
79
|
+
speed: {
|
|
80
|
+
type: 'number',
|
|
81
|
+
description: 'Speaking rate multiplier (0.5=half speed, 1.0=normal, 2.0=double speed)',
|
|
82
|
+
minimum: 0.5,
|
|
83
|
+
maximum: 2.0,
|
|
84
|
+
default: 1.0
|
|
85
|
+
},
|
|
86
|
+
volume: {
|
|
87
|
+
type: 'number',
|
|
88
|
+
description: 'Volume adjustment in dB (0=no change, positive=louder, negative=quieter)',
|
|
89
|
+
default: 0
|
|
90
|
+
},
|
|
91
|
+
temperature: {
|
|
92
|
+
type: 'number',
|
|
93
|
+
description: 'Expressiveness/emotion control (0=consistent and calm, 1=varied and emotional)',
|
|
94
|
+
minimum: 0,
|
|
95
|
+
maximum: 1,
|
|
96
|
+
default: 0.7
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
required: ['text']
|
|
100
|
+
};
|
|
101
|
+
service;
|
|
102
|
+
constructor() {
|
|
103
|
+
this.service = new FishAudioSDKService();
|
|
104
|
+
}
|
|
105
|
+
async run(input) {
|
|
106
|
+
try {
|
|
107
|
+
// Validate input
|
|
108
|
+
if (!input.text || input.text.trim().length === 0) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: 'Text input is required'
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (input.text.length > 10000) {
|
|
115
|
+
return {
|
|
116
|
+
success: false,
|
|
117
|
+
error: 'Text length exceeds maximum limit of 10,000 characters'
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const config = loadConfig();
|
|
121
|
+
// Select reference ID based on input parameters
|
|
122
|
+
let selectedReferenceId;
|
|
123
|
+
if (input.reference_id || input.reference_name || input.reference_tag) {
|
|
124
|
+
// Use reference selector if references are configured
|
|
125
|
+
if (config.references && config.references.length > 0) {
|
|
126
|
+
const selector = new ReferenceSelector(config.references, config.defaultReference);
|
|
127
|
+
selectedReferenceId = selector.selectReference({
|
|
128
|
+
id: input.reference_id,
|
|
129
|
+
name: input.reference_name,
|
|
130
|
+
tag: input.reference_tag
|
|
131
|
+
});
|
|
132
|
+
if (!selectedReferenceId && (input.reference_name || input.reference_tag)) {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: `No reference found matching: ${input.reference_name || input.reference_tag}`
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Fallback to direct ID if no references configured
|
|
141
|
+
selectedReferenceId = input.reference_id;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Use default reference or backward compatible referenceId
|
|
146
|
+
selectedReferenceId = config.defaultReference || config.referenceId;
|
|
147
|
+
}
|
|
148
|
+
// Prepare parameters
|
|
149
|
+
const ttsParams = {
|
|
150
|
+
text: input.text,
|
|
151
|
+
referenceId: selectedReferenceId,
|
|
152
|
+
format: (input.format || config.outputFormat),
|
|
153
|
+
mp3Bitrate: (input.mp3_bitrate || config.mp3Bitrate),
|
|
154
|
+
normalize: input.normalize !== false,
|
|
155
|
+
latency: (input.latency || 'balanced'),
|
|
156
|
+
streaming: input.streaming ?? config.streaming,
|
|
157
|
+
speed: input.speed,
|
|
158
|
+
volume: input.volume,
|
|
159
|
+
temperature: input.temperature,
|
|
160
|
+
};
|
|
161
|
+
// Determine output path
|
|
162
|
+
const outputPath = input.output_path || getOutputPath(ttsParams.format || 'mp3');
|
|
163
|
+
// Determine if auto-play is enabled
|
|
164
|
+
const shouldAutoPlay = input.auto_play ?? config.autoPlay;
|
|
165
|
+
// Determine if WebSocket streaming is enabled
|
|
166
|
+
const useWebSocketStreaming = input.websocket_streaming ?? config.websocketStreaming;
|
|
167
|
+
// WebSocket streaming mode with real-time playback
|
|
168
|
+
if (useWebSocketStreaming) {
|
|
169
|
+
return await this.handleWebSocketStreaming(input, ttsParams, outputPath, shouldAutoPlay || false);
|
|
170
|
+
}
|
|
171
|
+
if (ttsParams.streaming) {
|
|
172
|
+
// HTTP Streaming mode
|
|
173
|
+
const totalBytes = await this.service.generateSpeechStream(ttsParams, outputPath);
|
|
174
|
+
// Auto-play if requested
|
|
175
|
+
if (shouldAutoPlay && isAudioPlaybackSupported()) {
|
|
176
|
+
try {
|
|
177
|
+
await playAudio(outputPath);
|
|
178
|
+
}
|
|
179
|
+
catch (playError) {
|
|
180
|
+
logger.error('Audio playback failed:', playError);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
success: true,
|
|
185
|
+
file_path: outputPath,
|
|
186
|
+
format: ttsParams.format,
|
|
187
|
+
played: shouldAutoPlay || false
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Non-streaming mode
|
|
192
|
+
const response = await this.service.generateSpeech(ttsParams);
|
|
193
|
+
// Save to file if output path is specified
|
|
194
|
+
if (outputPath) {
|
|
195
|
+
writeFileSync(outputPath, response.audio);
|
|
196
|
+
// Auto-play if requested
|
|
197
|
+
if (shouldAutoPlay && isAudioPlaybackSupported()) {
|
|
198
|
+
try {
|
|
199
|
+
await playAudio(outputPath);
|
|
200
|
+
}
|
|
201
|
+
catch (playError) {
|
|
202
|
+
logger.error('Audio playback failed:', playError);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
success: true,
|
|
207
|
+
file_path: outputPath,
|
|
208
|
+
format: response.format,
|
|
209
|
+
played: shouldAutoPlay || false
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Return base64 encoded audio
|
|
214
|
+
return {
|
|
215
|
+
success: true,
|
|
216
|
+
audio_data: response.audio.toString('base64'),
|
|
217
|
+
format: response.format
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (error instanceof FishAudioError) {
|
|
224
|
+
return {
|
|
225
|
+
success: false,
|
|
226
|
+
error: `${error.message} (${error.code})`
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
success: false,
|
|
231
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred'
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async handleWebSocketStreaming(input, ttsParams, outputPath, shouldAutoPlay) {
|
|
236
|
+
const writeStream = outputPath ? createWriteStream(outputPath) : null;
|
|
237
|
+
let realTimePlayer = null;
|
|
238
|
+
let totalBytes = 0;
|
|
239
|
+
const audioChunks = [];
|
|
240
|
+
try {
|
|
241
|
+
// Set up real-time player if requested
|
|
242
|
+
const config = loadConfig();
|
|
243
|
+
const shouldRealtimePlay = input.realtime_play ?? config.realtimePlay;
|
|
244
|
+
if (shouldRealtimePlay && isAudioPlaybackSupported()) {
|
|
245
|
+
realTimePlayer = new RealTimeAudioPlayer();
|
|
246
|
+
realTimePlayer.start(ttsParams.format || 'opus');
|
|
247
|
+
}
|
|
248
|
+
// Split text into chunks for streaming
|
|
249
|
+
const textChunks = this.splitTextIntoChunks(input.text);
|
|
250
|
+
// Stream via WebSocket
|
|
251
|
+
const audioStream = this.service.generateSpeechWebSocket(ttsParams, textChunks);
|
|
252
|
+
for await (const audioChunk of audioStream) {
|
|
253
|
+
totalBytes += audioChunk.length;
|
|
254
|
+
// Write to file if output path specified
|
|
255
|
+
if (writeStream) {
|
|
256
|
+
writeStream.write(audioChunk);
|
|
257
|
+
}
|
|
258
|
+
// Play in real-time if requested
|
|
259
|
+
if (realTimePlayer) {
|
|
260
|
+
realTimePlayer.write(audioChunk);
|
|
261
|
+
}
|
|
262
|
+
// Collect chunks for post-playback if auto-play is enabled
|
|
263
|
+
if (shouldAutoPlay && !shouldRealtimePlay) {
|
|
264
|
+
audioChunks.push(audioChunk);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Close write stream
|
|
268
|
+
if (writeStream) {
|
|
269
|
+
writeStream.end();
|
|
270
|
+
}
|
|
271
|
+
// Stop real-time player
|
|
272
|
+
if (realTimePlayer) {
|
|
273
|
+
realTimePlayer.stop();
|
|
274
|
+
}
|
|
275
|
+
// Auto-play collected audio if requested (and not already played in real-time)
|
|
276
|
+
let played = false;
|
|
277
|
+
if (shouldAutoPlay && !shouldRealtimePlay && outputPath && isAudioPlaybackSupported()) {
|
|
278
|
+
try {
|
|
279
|
+
await playAudio(outputPath);
|
|
280
|
+
played = true;
|
|
281
|
+
}
|
|
282
|
+
catch (playError) {
|
|
283
|
+
logger.error('Audio playback failed:', playError);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
else if (shouldRealtimePlay) {
|
|
287
|
+
played = true;
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
success: true,
|
|
291
|
+
file_path: outputPath || undefined,
|
|
292
|
+
format: ttsParams.format,
|
|
293
|
+
played,
|
|
294
|
+
streaming_mode: 'websocket',
|
|
295
|
+
total_bytes: totalBytes
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
// Clean up on error
|
|
300
|
+
if (writeStream) {
|
|
301
|
+
writeStream.end();
|
|
302
|
+
}
|
|
303
|
+
if (realTimePlayer) {
|
|
304
|
+
realTimePlayer.stop();
|
|
305
|
+
}
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
splitTextIntoChunks(text, chunkSize = 100) {
|
|
310
|
+
const sentences = text.match(/[^.!?]+[.!?]+/g) || [text];
|
|
311
|
+
const chunks = [];
|
|
312
|
+
let currentChunk = '';
|
|
313
|
+
for (const sentence of sentences) {
|
|
314
|
+
if (currentChunk.length + sentence.length > chunkSize && currentChunk.length > 0) {
|
|
315
|
+
chunks.push(currentChunk.trim());
|
|
316
|
+
currentChunk = sentence;
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
currentChunk += sentence;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (currentChunk.trim()) {
|
|
323
|
+
chunks.push(currentChunk.trim());
|
|
324
|
+
}
|
|
325
|
+
return chunks;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=tts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts.js","sourceRoot":"","sources":["../../src/tools/tts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export interface ReferenceConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
tags?: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface Config {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
modelId: string;
|
|
9
|
+
referenceId?: string;
|
|
10
|
+
references?: ReferenceConfig[];
|
|
11
|
+
defaultReference?: string;
|
|
12
|
+
outputFormat: AudioFormat;
|
|
13
|
+
streaming: boolean;
|
|
14
|
+
mp3Bitrate: Mp3Bitrate;
|
|
15
|
+
audioOutputDir: string;
|
|
16
|
+
autoPlay?: boolean;
|
|
17
|
+
websocketStreaming?: boolean;
|
|
18
|
+
realtimePlay?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export type AudioFormat = 'mp3' | 'wav' | 'pcm' | 'opus';
|
|
21
|
+
export type Mp3Bitrate = 64 | 128 | 192;
|
|
22
|
+
export type LatencyMode = 'normal' | 'balanced';
|
|
23
|
+
export interface TTSParams {
|
|
24
|
+
text: string;
|
|
25
|
+
referenceId?: string;
|
|
26
|
+
format?: AudioFormat;
|
|
27
|
+
mp3Bitrate?: Mp3Bitrate;
|
|
28
|
+
normalize?: boolean;
|
|
29
|
+
latency?: LatencyMode;
|
|
30
|
+
chunkLength?: number;
|
|
31
|
+
streaming?: boolean;
|
|
32
|
+
websocketStreaming?: boolean;
|
|
33
|
+
speed?: number;
|
|
34
|
+
volume?: number;
|
|
35
|
+
temperature?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface TTSResponse {
|
|
38
|
+
audio: Buffer;
|
|
39
|
+
format: string;
|
|
40
|
+
duration?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface TTSToolParams {
|
|
43
|
+
text: string;
|
|
44
|
+
reference_id?: string;
|
|
45
|
+
reference_name?: string;
|
|
46
|
+
reference_tag?: string;
|
|
47
|
+
streaming?: boolean;
|
|
48
|
+
websocket_streaming?: boolean;
|
|
49
|
+
realtime_play?: boolean;
|
|
50
|
+
format?: AudioFormat;
|
|
51
|
+
mp3_bitrate?: Mp3Bitrate;
|
|
52
|
+
normalize?: boolean;
|
|
53
|
+
latency?: LatencyMode;
|
|
54
|
+
output_path?: string;
|
|
55
|
+
auto_play?: boolean;
|
|
56
|
+
speed?: number;
|
|
57
|
+
volume?: number;
|
|
58
|
+
temperature?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface TTSToolResponse {
|
|
61
|
+
success: boolean;
|
|
62
|
+
audio_data?: string;
|
|
63
|
+
file_path?: string;
|
|
64
|
+
format?: string;
|
|
65
|
+
played?: boolean;
|
|
66
|
+
streaming_mode?: 'http' | 'websocket';
|
|
67
|
+
total_bytes?: number;
|
|
68
|
+
error?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface FishAudioAPIRequest {
|
|
71
|
+
text: string;
|
|
72
|
+
reference_id?: string;
|
|
73
|
+
chunk_length?: number;
|
|
74
|
+
format?: string;
|
|
75
|
+
mp3_bitrate?: number;
|
|
76
|
+
normalize?: boolean;
|
|
77
|
+
latency?: string;
|
|
78
|
+
streaming?: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface FishAudioAPIResponse {
|
|
81
|
+
status: string;
|
|
82
|
+
data?: any;
|
|
83
|
+
error?: string;
|
|
84
|
+
}
|
|
85
|
+
export declare enum ErrorCode {
|
|
86
|
+
INVALID_API_KEY = "INVALID_API_KEY",
|
|
87
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
88
|
+
INVALID_PARAMS = "INVALID_PARAMS",
|
|
89
|
+
QUOTA_EXCEEDED = "QUOTA_EXCEEDED",
|
|
90
|
+
SERVER_ERROR = "SERVER_ERROR",
|
|
91
|
+
UNKNOWN_ERROR = "UNKNOWN_ERROR"
|
|
92
|
+
}
|
|
93
|
+
export declare class FishAudioError extends Error {
|
|
94
|
+
code: ErrorCode;
|
|
95
|
+
details?: any | undefined;
|
|
96
|
+
constructor(message: string, code: ErrorCode, details?: any | undefined);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,WAAW,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AACzD,MAAM,MAAM,UAAU,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;AACxC,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,SAAS;IACnB,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,cAAc,mBAAmB;IACjC,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;CAChC;AAED,qBAAa,cAAe,SAAQ,KAAK;IAG9B,IAAI,EAAE,SAAS;IACf,OAAO,CAAC,EAAE,GAAG;gBAFpB,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,GAAG,YAAA;CAKvB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export var ErrorCode;
|
|
2
|
+
(function (ErrorCode) {
|
|
3
|
+
ErrorCode["INVALID_API_KEY"] = "INVALID_API_KEY";
|
|
4
|
+
ErrorCode["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
5
|
+
ErrorCode["INVALID_PARAMS"] = "INVALID_PARAMS";
|
|
6
|
+
ErrorCode["QUOTA_EXCEEDED"] = "QUOTA_EXCEEDED";
|
|
7
|
+
ErrorCode["SERVER_ERROR"] = "SERVER_ERROR";
|
|
8
|
+
ErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
9
|
+
})(ErrorCode || (ErrorCode = {}));
|
|
10
|
+
export class FishAudioError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
details;
|
|
13
|
+
constructor(message, code, details) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.details = details;
|
|
17
|
+
this.name = 'FishAudioError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AA6FA,MAAM,CAAN,IAAY,SAOX;AAPD,WAAY,SAAS;IACnB,gDAAmC,CAAA;IACnC,4CAA+B,CAAA;IAC/B,8CAAiC,CAAA;IACjC,8CAAiC,CAAA;IACjC,0CAA6B,CAAA;IAC7B,4CAA+B,CAAA;AACjC,CAAC,EAPW,SAAS,KAAT,SAAS,QAOpB;AAED,MAAM,OAAO,cAAe,SAAQ,KAAK;IAG9B;IACA;IAHT,YACE,OAAe,EACR,IAAe,EACf,OAAa;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAW;QACf,YAAO,GAAP,OAAO,CAAM;QAGpB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audioPlayer.d.ts","sourceRoot":"","sources":["../../src/utils/audioPlayer.ts"],"names":[],"mappings":"AAOA,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB/D;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAGlD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { platform } from 'os';
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
export async function playAudio(filePath) {
|
|
7
|
+
const os = platform();
|
|
8
|
+
let command;
|
|
9
|
+
switch (os) {
|
|
10
|
+
case 'darwin': // macOS
|
|
11
|
+
command = `afplay "${filePath}"`;
|
|
12
|
+
break;
|
|
13
|
+
case 'win32': // Windows
|
|
14
|
+
command = `powershell -c "(New-Object Media.SoundPlayer '${filePath}').PlaySync()"`;
|
|
15
|
+
break;
|
|
16
|
+
case 'linux':
|
|
17
|
+
// Try multiple players in order of preference
|
|
18
|
+
command = `which aplay >/dev/null 2>&1 && aplay "${filePath}" || which mpg123 >/dev/null 2>&1 && mpg123 "${filePath}" || which ffplay >/dev/null 2>&1 && ffplay -nodisp -autoexit "${filePath}" || echo "No audio player found"`;
|
|
19
|
+
break;
|
|
20
|
+
default:
|
|
21
|
+
throw new Error(`Unsupported platform: ${os}`);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
await execAsync(command);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
logger.error('Failed to play audio:', error);
|
|
28
|
+
throw new Error(`Audio playback failed: ${error}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function isAudioPlaybackSupported() {
|
|
32
|
+
const os = platform();
|
|
33
|
+
return ['darwin', 'win32', 'linux'].includes(os);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=audioPlayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audioPlayer.js","sourceRoot":"","sources":["../../src/utils/audioPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB;IAC9C,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,OAAe,CAAC;IAEpB,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,QAAQ,EAAE,QAAQ;YACrB,OAAO,GAAG,WAAW,QAAQ,GAAG,CAAC;YACjC,MAAM;QACR,KAAK,OAAO,EAAE,UAAU;YACtB,OAAO,GAAG,iDAAiD,QAAQ,gBAAgB,CAAC;YACpF,MAAM;QACR,KAAK,OAAO;YACV,8CAA8C;YAC9C,OAAO,GAAG,yCAAyC,QAAQ,gDAAgD,QAAQ,kEAAkE,QAAQ,mCAAmC,CAAC;YACjO,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA4C,MAAM,mBAAmB,CAAC;AAuErF,wBAAgB,UAAU,IAAI,MAAM,CAsDnC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { config as dotenvConfig } from 'dotenv';
|
|
2
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join, resolve } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { logger } from './logger.js';
|
|
6
|
+
dotenvConfig();
|
|
7
|
+
function parseBoolean(value, defaultValue) {
|
|
8
|
+
if (!value)
|
|
9
|
+
return defaultValue;
|
|
10
|
+
return value.toLowerCase() === 'true';
|
|
11
|
+
}
|
|
12
|
+
function parseAudioFormat(value, defaultValue) {
|
|
13
|
+
if (!value)
|
|
14
|
+
return defaultValue;
|
|
15
|
+
const validFormats = ['mp3', 'wav', 'pcm', 'opus'];
|
|
16
|
+
const format = value.toLowerCase();
|
|
17
|
+
return validFormats.includes(format) ? format : defaultValue;
|
|
18
|
+
}
|
|
19
|
+
function parseMp3Bitrate(value, defaultValue) {
|
|
20
|
+
if (!value)
|
|
21
|
+
return defaultValue;
|
|
22
|
+
const bitrate = parseInt(value);
|
|
23
|
+
const validBitrates = [64, 128, 192];
|
|
24
|
+
return validBitrates.includes(bitrate) ? bitrate : defaultValue;
|
|
25
|
+
}
|
|
26
|
+
let configCache = null;
|
|
27
|
+
function parseReferences() {
|
|
28
|
+
const references = [];
|
|
29
|
+
// Parse FISH_REFERENCES as JSON array
|
|
30
|
+
const referencesStr = process.env.FISH_REFERENCES;
|
|
31
|
+
if (referencesStr) {
|
|
32
|
+
try {
|
|
33
|
+
const parsedRefs = JSON.parse(referencesStr);
|
|
34
|
+
if (Array.isArray(parsedRefs)) {
|
|
35
|
+
for (const ref of parsedRefs) {
|
|
36
|
+
if (ref.reference_id || ref.id) {
|
|
37
|
+
references.push({
|
|
38
|
+
id: ref.reference_id || ref.id,
|
|
39
|
+
name: ref.name,
|
|
40
|
+
tags: ref.tags
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
logger.error('Failed to parse FISH_REFERENCES as JSON:', error);
|
|
48
|
+
logger.error('Please use JSON array format: [{"reference_id":"id1","name":"Alice","tags":["female","english"]}]');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Fallback: support individual reference configs for backward compatibility
|
|
52
|
+
if (references.length === 0) {
|
|
53
|
+
for (let i = 1; i <= 10; i++) {
|
|
54
|
+
const id = process.env[`FISH_REFERENCE_${i}_ID`];
|
|
55
|
+
if (id) {
|
|
56
|
+
references.push({
|
|
57
|
+
id,
|
|
58
|
+
name: process.env[`FISH_REFERENCE_${i}_NAME`],
|
|
59
|
+
tags: process.env[`FISH_REFERENCE_${i}_TAGS`]?.split(',').map(t => t.trim())
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return references;
|
|
65
|
+
}
|
|
66
|
+
export function loadConfig() {
|
|
67
|
+
if (configCache) {
|
|
68
|
+
return configCache;
|
|
69
|
+
}
|
|
70
|
+
const apiKey = process.env.FISH_API_KEY;
|
|
71
|
+
if (!apiKey) {
|
|
72
|
+
throw new Error('FISH_API_KEY environment variable is required');
|
|
73
|
+
}
|
|
74
|
+
// Default to user's home directory for audio output
|
|
75
|
+
const defaultOutputDir = join(homedir(), '.fish-audio-mcp', 'audio_output');
|
|
76
|
+
let audioOutputDir = process.env.AUDIO_OUTPUT_DIR || defaultOutputDir;
|
|
77
|
+
// Expand ~ to home directory if present
|
|
78
|
+
if (audioOutputDir.startsWith('~/')) {
|
|
79
|
+
audioOutputDir = join(homedir(), audioOutputDir.slice(2));
|
|
80
|
+
}
|
|
81
|
+
const resolvedOutputDir = resolve(audioOutputDir);
|
|
82
|
+
// Create output directory if it doesn't exist
|
|
83
|
+
try {
|
|
84
|
+
if (!existsSync(resolvedOutputDir)) {
|
|
85
|
+
mkdirSync(resolvedOutputDir, { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
logger.error(`Warning: Could not create audio output directory at ${resolvedOutputDir}. Audio files will be saved to memory only.`);
|
|
90
|
+
}
|
|
91
|
+
const streaming = parseBoolean(process.env.FISH_STREAMING, false);
|
|
92
|
+
const autoPlay = parseBoolean(process.env.FISH_AUTO_PLAY, false);
|
|
93
|
+
// Parse references
|
|
94
|
+
const references = parseReferences();
|
|
95
|
+
const defaultReference = process.env.FISH_DEFAULT_REFERENCE || process.env.FISH_REFERENCE_ID;
|
|
96
|
+
const config = {
|
|
97
|
+
apiKey,
|
|
98
|
+
modelId: process.env.FISH_MODEL_ID || 's1',
|
|
99
|
+
referenceId: process.env.FISH_REFERENCE_ID, // Keep for backward compatibility
|
|
100
|
+
references,
|
|
101
|
+
defaultReference,
|
|
102
|
+
outputFormat: parseAudioFormat(process.env.FISH_OUTPUT_FORMAT, 'mp3'),
|
|
103
|
+
streaming: streaming,
|
|
104
|
+
mp3Bitrate: parseMp3Bitrate(process.env.FISH_MP3_BITRATE, 128),
|
|
105
|
+
audioOutputDir: resolvedOutputDir,
|
|
106
|
+
autoPlay: autoPlay,
|
|
107
|
+
websocketStreaming: false, // Default to false for HTTP streaming
|
|
108
|
+
realtimePlay: false // Default to false for standard playback
|
|
109
|
+
};
|
|
110
|
+
configCache = config;
|
|
111
|
+
return config;
|
|
112
|
+
}
|
|
113
|
+
export function getOutputPath(format) {
|
|
114
|
+
const config = loadConfig();
|
|
115
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
116
|
+
const filename = `tts_${timestamp}.${format}`;
|
|
117
|
+
return join(config.audioOutputDir, filename);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,YAAY,EAAE,CAAC;AAEf,SAAS,YAAY,CAAC,KAAyB,EAAE,YAAqB;IACpE,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC;IAChC,OAAO,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAyB,EAAE,YAAyB;IAC5E,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC;IAChC,MAAM,YAAY,GAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,EAAiB,CAAC;IAClD,OAAO,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;AAC/D,CAAC;AAED,SAAS,eAAe,CAAC,KAAyB,EAAE,YAAwB;IAC1E,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC;IAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,aAAa,GAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,aAAa,CAAC,QAAQ,CAAC,OAAqB,CAAC,CAAC,CAAC,CAAE,OAAsB,CAAC,CAAC,CAAC,YAAY,CAAC;AAChG,CAAC;AAED,IAAI,WAAW,GAAkB,IAAI,CAAC;AAEtC,SAAS,eAAe;IACtB,MAAM,UAAU,GAAsB,EAAE,CAAC;IAEzC,sCAAsC;IACtC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAClD,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;oBAC7B,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;wBAC/B,UAAU,CAAC,IAAI,CAAC;4BACd,EAAE,EAAE,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,EAAE;4BAC9B,IAAI,EAAE,GAAG,CAAC,IAAI;4BACd,IAAI,EAAE,GAAG,CAAC,IAAI;yBACf,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;YAChE,MAAM,CAAC,KAAK,CAAC,mGAAmG,CAAC,CAAC;QACpH,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,EAAE,EAAE,CAAC;gBACP,UAAU,CAAC,IAAI,CAAC;oBACd,EAAE;oBACF,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC;oBAC7C,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBAC7E,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,oDAAoD;IACpD,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC;IAC5E,IAAI,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,gBAAgB,CAAC;IAEtE,wCAAwC;IACxC,IAAI,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAElD,8CAA8C;IAC9C,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACnC,SAAS,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uDAAuD,iBAAiB,6CAA6C,CAAC,CAAC;IACtI,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAEjE,mBAAmB;IACnB,MAAM,UAAU,GAAG,eAAe,EAAE,CAAC;IACrC,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAE7F,MAAM,MAAM,GAAW;QACrB,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,IAAI;QAC1C,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,kCAAkC;QAC9E,UAAU;QACV,gBAAgB;QAChB,YAAY,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC;QACrE,SAAS,EAAE,SAAS;QACpB,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,GAAG,CAAC;QAC9D,cAAc,EAAE,iBAAiB;QACjC,QAAQ,EAAE,QAAQ;QAClB,kBAAkB,EAAE,KAAK,EAAG,sCAAsC;QAClE,YAAY,EAAE,KAAK,CAAE,yCAAyC;KAC/D,CAAC;IAEF,WAAW,GAAG,MAAM,CAAC;IACrB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,CAAC;IAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC"}
|