import { useServerStore } from '@/stores/serverStore'; import type { VoiceProfileCreate, VoiceProfileResponse, ProfileSampleResponse, GenerationRequest, GenerationResponse, HistoryQuery, HistoryListResponse, HistoryResponse, TranscriptionResponse, HealthResponse, ModelStatusListResponse, ModelDownloadRequest, ActiveTasksResponse, } from './types'; class ApiClient { private getBaseUrl(): string { const serverUrl = useServerStore.getState().serverUrl; return serverUrl; } private async request(endpoint: string, options?: RequestInit): Promise { const url = `${this.getBaseUrl()}${endpoint}`; const response = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', ...options?.headers, }, }); if (!response.ok) { const error = await response.json().catch(() => ({ detail: response.statusText, })); throw new Error(error.detail || `HTTP error! status: ${response.status}`); } return response.json(); } // Health async getHealth(): Promise { return this.request('/health'); } // Profiles async createProfile(data: VoiceProfileCreate): Promise { return this.request('/profiles', { method: 'POST', body: JSON.stringify(data), }); } async listProfiles(): Promise { return this.request('/profiles'); } async getProfile(profileId: string): Promise { return this.request(`/profiles/${profileId}`); } async updateProfile(profileId: string, data: VoiceProfileCreate): Promise { return this.request(`/profiles/${profileId}`, { method: 'PUT', body: JSON.stringify(data), }); } async deleteProfile(profileId: string): Promise { await this.request(`/profiles/${profileId}`, { method: 'DELETE', }); } async addProfileSample( profileId: string, file: File, referenceText: string, ): Promise { const url = `${this.getBaseUrl()}/profiles/${profileId}/samples`; const formData = new FormData(); formData.append('file', file); formData.append('reference_text', referenceText); const response = await fetch(url, { method: 'POST', body: formData, }); if (!response.ok) { const error = await response.json().catch(() => ({ detail: response.statusText, })); throw new Error(error.detail || `HTTP error! status: ${response.status}`); } return response.json(); } async listProfileSamples(profileId: string): Promise { return this.request(`/profiles/${profileId}/samples`); } async deleteProfileSample(sampleId: string): Promise { await this.request(`/profiles/samples/${sampleId}`, { method: 'DELETE', }); } async exportProfile(profileId: string): Promise { const url = `${this.getBaseUrl()}/profiles/${profileId}/export`; const response = await fetch(url); if (!response.ok) { const error = await response.json().catch(() => ({ detail: response.statusText, })); throw new Error(error.detail || `HTTP error! status: ${response.status}`); } return response.blob(); } async importProfile(file: File): Promise { const url = `${this.getBaseUrl()}/profiles/import`; const formData = new FormData(); formData.append('file', file); const response = await fetch(url, { method: 'POST', body: formData, }); if (!response.ok) { const error = await response.json().catch(() => ({ detail: response.statusText, })); throw new Error(error.detail || `HTTP error! status: ${response.status}`); } return response.json(); } // Generation async generateSpeech(data: GenerationRequest): Promise { return this.request('/generate', { method: 'POST', body: JSON.stringify(data), }); } // History async listHistory(query?: HistoryQuery): Promise { const params = new URLSearchParams(); if (query?.profile_id) params.append('profile_id', query.profile_id); if (query?.search) params.append('search', query.search); if (query?.limit) params.append('limit', query.limit.toString()); if (query?.offset) params.append('offset', query.offset.toString()); const queryString = params.toString(); const endpoint = queryString ? `/history?${queryString}` : '/history'; return this.request(endpoint); } async getGeneration(generationId: string): Promise { return this.request(`/history/${generationId}`); } async deleteGeneration(generationId: string): Promise { await this.request(`/history/${generationId}`, { method: 'DELETE', }); } // Audio getAudioUrl(audioId: string): string { return `${this.getBaseUrl()}/audio/${audioId}`; } getSampleUrl(sampleId: string): string { return `${this.getBaseUrl()}/samples/${sampleId}`; } // Transcription async transcribeAudio(file: File, language?: 'en' | 'zh'): Promise { const formData = new FormData(); formData.append('file', file); if (language) { formData.append('language', language); } const url = `${this.getBaseUrl()}/transcribe`; const response = await fetch(url, { method: 'POST', body: formData, }); if (!response.ok) { const error = await response.json().catch(() => ({ detail: response.statusText, })); throw new Error(error.detail || `HTTP error! status: ${response.status}`); } return response.json(); } // Model Management async getModelStatus(): Promise { return this.request('/models/status'); } async triggerModelDownload(modelName: string): Promise<{ message: string }> { return this.request<{ message: string }>('/models/download', { method: 'POST', body: JSON.stringify({ model_name: modelName } as ModelDownloadRequest), }); } async deleteModel(modelName: string): Promise<{ message: string }> { return this.request<{ message: string }>(`/models/${modelName}`, { method: 'DELETE', }); } // Task Management async getActiveTasks(): Promise { return this.request('/tasks/active'); } } export const apiClient = new ApiClient();