Voice libary data presistence after codex
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Assistant, CallLog, InteractionDetail, KnowledgeBase, KnowledgeDocument, Voice, Workflow, WorkflowEdge, WorkflowNode } from '../types';
|
||||
import { Assistant, CallLog, InteractionDetail, KnowledgeBase, KnowledgeDocument, VendorCredential, Voice, Workflow, WorkflowEdge, WorkflowNode } from '../types';
|
||||
import { apiRequest } from './apiClient';
|
||||
|
||||
type AnyRecord = Record<string, any>;
|
||||
@@ -46,10 +46,27 @@ const mapAssistant = (raw: AnyRecord): Assistant => ({
|
||||
const mapVoice = (raw: AnyRecord): Voice => ({
|
||||
id: String(readField(raw, ['id'], '')),
|
||||
name: readField(raw, ['name'], ''),
|
||||
vendor: readField(raw, ['vendor'], ''),
|
||||
vendor: ((): string => {
|
||||
const vendor = String(readField(raw, ['vendor'], ''));
|
||||
return vendor.toLowerCase() === 'siliconflow' ? '硅基流动' : vendor;
|
||||
})(),
|
||||
gender: readField(raw, ['gender'], ''),
|
||||
language: readField(raw, ['language'], ''),
|
||||
description: readField(raw, ['description'], ''),
|
||||
model: readField(raw, ['model'], ''),
|
||||
voiceKey: readField(raw, ['voiceKey', 'voice_key'], ''),
|
||||
speed: Number(readField(raw, ['speed'], 1)),
|
||||
gain: Number(readField(raw, ['gain'], 0)),
|
||||
pitch: Number(readField(raw, ['pitch'], 0)),
|
||||
enabled: Boolean(readField(raw, ['enabled'], true)),
|
||||
isSystem: Boolean(readField(raw, ['isSystem', 'is_system'], false)),
|
||||
});
|
||||
|
||||
const mapVendorCredential = (raw: AnyRecord): VendorCredential => ({
|
||||
vendorKey: String(readField(raw, ['vendorKey', 'vendor_key'], '')),
|
||||
vendorName: readField(raw, ['vendorName', 'vendor_name'], ''),
|
||||
apiKey: readField(raw, ['apiKey', 'api_key'], ''),
|
||||
baseUrl: readField(raw, ['baseUrl', 'base_url'], ''),
|
||||
});
|
||||
|
||||
const mapWorkflowNode = (raw: AnyRecord): WorkflowNode => ({
|
||||
@@ -178,6 +195,76 @@ export const fetchVoices = async (): Promise<Voice[]> => {
|
||||
return list.map((item) => mapVoice(item));
|
||||
};
|
||||
|
||||
export const createVoice = async (data: Partial<Voice>): Promise<Voice> => {
|
||||
const payload = {
|
||||
id: data.id || undefined,
|
||||
name: data.name || 'New Voice',
|
||||
vendor: data.vendor === '硅基流动' ? 'SiliconFlow' : (data.vendor || 'SiliconFlow'),
|
||||
gender: data.gender || 'Female',
|
||||
language: data.language || 'zh',
|
||||
description: data.description || '',
|
||||
model: data.model || undefined,
|
||||
voice_key: data.voiceKey || undefined,
|
||||
speed: data.speed ?? 1,
|
||||
gain: data.gain ?? 0,
|
||||
pitch: data.pitch ?? 0,
|
||||
enabled: data.enabled ?? true,
|
||||
};
|
||||
const response = await apiRequest<AnyRecord>('/voices', { method: 'POST', body: payload });
|
||||
return mapVoice(response);
|
||||
};
|
||||
|
||||
export const updateVoice = async (id: string, data: Partial<Voice>): Promise<Voice> => {
|
||||
const payload = {
|
||||
name: data.name,
|
||||
vendor: data.vendor === '硅基流动' ? 'SiliconFlow' : data.vendor,
|
||||
gender: data.gender,
|
||||
language: data.language,
|
||||
description: data.description,
|
||||
model: data.model,
|
||||
voice_key: data.voiceKey,
|
||||
speed: data.speed,
|
||||
gain: data.gain,
|
||||
pitch: data.pitch,
|
||||
enabled: data.enabled,
|
||||
};
|
||||
const response = await apiRequest<AnyRecord>(`/voices/${id}`, { method: 'PUT', body: payload });
|
||||
return mapVoice(response);
|
||||
};
|
||||
|
||||
export const deleteVoice = async (id: string): Promise<void> => {
|
||||
await apiRequest(`/voices/${id}`, { method: 'DELETE' });
|
||||
};
|
||||
|
||||
export const previewVoice = async (id: string, text: string, speed?: number, apiKey?: string): Promise<string> => {
|
||||
const response = await apiRequest<{ success: boolean; audio_url?: string; error?: string }>(`/voices/${id}/preview`, {
|
||||
method: 'POST',
|
||||
body: { text, speed, api_key: apiKey },
|
||||
});
|
||||
if (!response.success || !response.audio_url) {
|
||||
throw new Error(response.error || 'Preview failed');
|
||||
}
|
||||
return response.audio_url;
|
||||
};
|
||||
|
||||
export const fetchVendorCredentials = async (): Promise<VendorCredential[]> => {
|
||||
const response = await apiRequest<{ list?: AnyRecord[] }>('/voices/vendors/credentials');
|
||||
const list = response.list || [];
|
||||
return list.map((item) => mapVendorCredential(item));
|
||||
};
|
||||
|
||||
export const saveVendorCredential = async (vendorKey: string, data: { vendorName: string; apiKey: string; baseUrl?: string }): Promise<VendorCredential> => {
|
||||
const response = await apiRequest<AnyRecord>(`/voices/vendors/credentials/${vendorKey}`, {
|
||||
method: 'PUT',
|
||||
body: {
|
||||
vendor_name: data.vendorName,
|
||||
api_key: data.apiKey,
|
||||
base_url: data.baseUrl || undefined,
|
||||
},
|
||||
});
|
||||
return mapVendorCredential(response);
|
||||
};
|
||||
|
||||
export const fetchWorkflows = async (): Promise<Workflow[]> => {
|
||||
const response = await apiRequest<{ list?: AnyRecord[] } | AnyRecord[]>('/workflows');
|
||||
const list = Array.isArray(response) ? response : (response.list || []);
|
||||
|
||||
Reference in New Issue
Block a user