fix: 修复 Hedra 口型合成工具的 API 调用问题

- 修复前端和后端参数类型不匹配问题
- 在前端服务中添加 fileToBytes 方法,将 File 对象转换为字节数组
- 更新后端 HedraFileUploadRequest 结构,添加 purpose 字段
- 修复 Tauri 命令参数接收方式,使用 params 而不是 request
- 将 bowong_wait_for_task_completion 的模拟实现替换为真实的 API 调用
- 使用 wait_for_task_completion 方法实现真实的任务等待逻辑

现在 Hedra 工具应该能够正确调用后端 API 进行文件上传和任务处理
This commit is contained in:
imeepos 2025-08-01 11:13:25 +08:00
parent 0ec73f03ca
commit 538254ee38
3 changed files with 46 additions and 16 deletions

View File

@ -263,6 +263,7 @@ pub struct ComfyUISyncExecuteRequest {
pub struct HedraFileUploadRequest {
pub file_data: Vec<u8>,
pub filename: String,
pub purpose: Option<String>, // 'image', 'audio', 'video', 'voice'
}
/// Hedra 任务提交请求

View File

@ -668,22 +668,25 @@ pub async fn bowong_batch_query_task_status(
/// 等待任务完成
#[command]
pub async fn bowong_wait_for_task_completion(
state: State<'_, AppState>,
task_id: String,
max_wait_time: u64,
poll_interval: u64,
) -> Result<TaskStatusResponse, String> {
// 模拟等待
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
// 克隆服务以避免跨 await 点持有 MutexGuard
let service = {
let service_guard = state.get_bowong_service()
.map_err(|e| format!("Failed to get BowongTextVideoAgent service: {}", e))?;
Ok(TaskStatusResponse {
task_id,
status: "completed".to_string(),
progress: Some(100.0),
result: Some(serde_json::json!({"output": "Task completed after waiting"})),
error: None,
created_at: Some("2024-01-01T00:00:00Z".to_string()),
updated_at: Some("2024-01-01T00:00:00Z".to_string()),
})
service_guard.as_ref()
.ok_or_else(|| "BowongTextVideoAgent service not initialized".to_string())?
.clone()
};
// 使用真实的轮询逻辑等待任务完成
service.wait_for_task_completion(&task_id, max_wait_time, poll_interval)
.await
.map_err(|e| format!("Failed to wait for task completion: {}", e))
}
// ============================================================================
@ -694,7 +697,7 @@ pub async fn bowong_wait_for_task_completion(
#[command]
pub async fn hedra_upload_file(
state: State<'_, AppState>,
request: HedraFileUploadRequest,
params: HedraFileUploadRequest,
) -> Result<FileUploadResponse, String> {
// 克隆服务以避免跨 await 点持有 MutexGuard
let service = {
@ -706,7 +709,7 @@ pub async fn hedra_upload_file(
.clone()
};
service.hedra_upload_file(&request)
service.hedra_upload_file(&params)
.await
.map_err(|e| format!("Failed to upload file to Hedra: {}", e))
}
@ -715,7 +718,7 @@ pub async fn hedra_upload_file(
#[command]
pub async fn hedra_submit_task(
state: State<'_, AppState>,
request: HedraTaskSubmitRequest,
params: HedraTaskSubmitRequest,
) -> Result<TaskResponse, String> {
// 克隆服务以避免跨 await 点持有 MutexGuard
let service = {
@ -727,7 +730,7 @@ pub async fn hedra_submit_task(
.clone()
};
service.hedra_submit_task(&request)
service.hedra_submit_task(&params)
.await
.map_err(|e| format!("Failed to submit Hedra task: {}", e))
}

View File

@ -606,7 +606,15 @@ export class BowongTextVideoAgentFastApiService implements BowongTextVideoAgentA
// ============================================================================
async hedraUploadFile(request: HedraFileUploadRequest): Promise<FileUploadResponse> {
return this.invokeAPI<FileUploadResponse>('hedra_upload_file', request);
// 将 File 对象转换为后端期望的格式
const fileData = await this.fileToBytes(request.local_file);
const backendRequest = {
file_data: Array.from(fileData), // 转换为数字数组
filename: request.local_file.name,
purpose: request.purpose || 'image'
};
return this.invokeAPI<FileUploadResponse>('hedra_upload_file', backendRequest);
}
async hedraSubmitTask(request: HedraTaskSubmitRequest): Promise<TaskResponse> {
@ -633,6 +641,24 @@ export class BowongTextVideoAgentFastApiService implements BowongTextVideoAgentA
// 工具方法
// ============================================================================
/**
* File
*/
private async fileToBytes(file: File): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
if (reader.result instanceof ArrayBuffer) {
resolve(new Uint8Array(reader.result));
} else {
reject(new Error('Failed to read file as ArrayBuffer'));
}
};
reader.onerror = () => reject(reader.error);
reader.readAsArrayBuffer(file);
});
}
/**
*
*/