mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-20 07:10:40 -07:00
Add generated API client files to git for CI builds
This commit is contained in:
@@ -50,7 +50,6 @@ logs/
|
|||||||
.env.local
|
.env.local
|
||||||
|
|
||||||
# Generated files
|
# Generated files
|
||||||
app/src/lib/api/
|
|
||||||
app/openapi.json
|
app/openapi.json
|
||||||
tauri/src-tauri/binaries/*
|
tauri/src-tauri/binaries/*
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
# Generated OpenAPI client will be placed here
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
import { useServerStore } from '@/stores/serverStore';
|
||||||
|
import type {
|
||||||
|
VoiceProfileCreate,
|
||||||
|
VoiceProfileResponse,
|
||||||
|
ProfileSampleResponse,
|
||||||
|
GenerationRequest,
|
||||||
|
GenerationResponse,
|
||||||
|
HistoryQuery,
|
||||||
|
HistoryListResponse,
|
||||||
|
HistoryResponse,
|
||||||
|
TranscriptionResponse,
|
||||||
|
HealthResponse,
|
||||||
|
ModelStatusListResponse,
|
||||||
|
ModelDownloadRequest,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
|
class ApiClient {
|
||||||
|
private getBaseUrl(): string {
|
||||||
|
const serverUrl = useServerStore.getState().serverUrl;
|
||||||
|
return serverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async request<T>(
|
||||||
|
endpoint: string,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<T> {
|
||||||
|
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<HealthResponse> {
|
||||||
|
return this.request<HealthResponse>('/health');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Profiles
|
||||||
|
async createProfile(data: VoiceProfileCreate): Promise<VoiceProfileResponse> {
|
||||||
|
return this.request<VoiceProfileResponse>('/profiles', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async listProfiles(): Promise<VoiceProfileResponse[]> {
|
||||||
|
return this.request<VoiceProfileResponse[]>('/profiles');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getProfile(profileId: string): Promise<VoiceProfileResponse> {
|
||||||
|
return this.request<VoiceProfileResponse>(`/profiles/${profileId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateProfile(
|
||||||
|
profileId: string,
|
||||||
|
data: VoiceProfileCreate,
|
||||||
|
): Promise<VoiceProfileResponse> {
|
||||||
|
return this.request<VoiceProfileResponse>(`/profiles/${profileId}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteProfile(profileId: string): Promise<void> {
|
||||||
|
await this.request<void>(`/profiles/${profileId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async addProfileSample(
|
||||||
|
profileId: string,
|
||||||
|
file: File,
|
||||||
|
referenceText: string,
|
||||||
|
): Promise<ProfileSampleResponse> {
|
||||||
|
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<ProfileSampleResponse[]> {
|
||||||
|
return this.request<ProfileSampleResponse[]>(
|
||||||
|
`/profiles/${profileId}/samples`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteProfileSample(sampleId: string): Promise<void> {
|
||||||
|
await this.request<void>(`/profiles/samples/${sampleId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generation
|
||||||
|
async generateSpeech(
|
||||||
|
data: GenerationRequest,
|
||||||
|
): Promise<GenerationResponse> {
|
||||||
|
return this.request<GenerationResponse>('/generate', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// History
|
||||||
|
async listHistory(query?: HistoryQuery): Promise<HistoryListResponse> {
|
||||||
|
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<HistoryListResponse>(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGeneration(generationId: string): Promise<HistoryResponse> {
|
||||||
|
return this.request<HistoryResponse>(`/history/${generationId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteGeneration(generationId: string): Promise<void> {
|
||||||
|
await this.request<void>(`/history/${generationId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
getAudioUrl(audioId: string): string {
|
||||||
|
return `${this.getBaseUrl()}/audio/${audioId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transcription
|
||||||
|
async transcribeAudio(
|
||||||
|
file: File,
|
||||||
|
language?: 'en' | 'zh',
|
||||||
|
): Promise<TranscriptionResponse> {
|
||||||
|
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<ModelStatusListResponse> {
|
||||||
|
return this.request<ModelStatusListResponse>('/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),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiClient = new ApiClient();
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
// API Types matching backend Pydantic models
|
||||||
|
|
||||||
|
export interface VoiceProfileCreate {
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
language: 'en' | 'zh';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VoiceProfileResponse {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
language: string;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProfileSampleCreate {
|
||||||
|
reference_text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProfileSampleResponse {
|
||||||
|
id: string;
|
||||||
|
profile_id: string;
|
||||||
|
audio_path: string;
|
||||||
|
reference_text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenerationRequest {
|
||||||
|
profile_id: string;
|
||||||
|
text: string;
|
||||||
|
language: 'en' | 'zh';
|
||||||
|
seed?: number;
|
||||||
|
model_size?: '1.7B' | '0.6B';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenerationResponse {
|
||||||
|
id: string;
|
||||||
|
profile_id: string;
|
||||||
|
text: string;
|
||||||
|
language: string;
|
||||||
|
audio_path: string;
|
||||||
|
duration: number;
|
||||||
|
seed?: number;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryQuery {
|
||||||
|
profile_id?: string;
|
||||||
|
search?: string;
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryResponse extends GenerationResponse {
|
||||||
|
profile_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryListResponse {
|
||||||
|
items: HistoryResponse[];
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TranscriptionRequest {
|
||||||
|
language?: 'en' | 'zh';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TranscriptionResponse {
|
||||||
|
text: string;
|
||||||
|
duration: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HealthResponse {
|
||||||
|
status: string;
|
||||||
|
model_loaded: boolean;
|
||||||
|
model_downloaded?: boolean;
|
||||||
|
model_size?: string;
|
||||||
|
gpu_available: boolean;
|
||||||
|
vram_used_mb?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelProgress {
|
||||||
|
model_name: string;
|
||||||
|
current: number;
|
||||||
|
total: number;
|
||||||
|
progress: number;
|
||||||
|
filename?: string;
|
||||||
|
status: 'downloading' | 'extracting' | 'complete' | 'error';
|
||||||
|
timestamp: string;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelStatus {
|
||||||
|
model_name: string;
|
||||||
|
display_name: string;
|
||||||
|
downloaded: boolean;
|
||||||
|
size_mb?: number;
|
||||||
|
loaded: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelStatusListResponse {
|
||||||
|
models: ModelStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelDownloadRequest {
|
||||||
|
model_name: string;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user