优化全能创作

This commit is contained in:
Azmat@qq.com
2026-09-11 19:11:27 +08:00
parent dbcac8a44b
commit 02e5dbfb60
25 changed files with 2398 additions and 462 deletions
+24 -44
View File
@@ -602,10 +602,11 @@ export const api = {
);
},
/**
* 发一条消息 → SSE 流。事件:tool / reasoning / delta / message / task / credits / done / error。
* 和 agentScriptStream 同一套 fetch + ReadableStream(EventSource 只支持 GET,这里要 POST 带 body)。
* 发一条消息 → 异步整理方案。成功 **202** `{conversation_id, agent_status}`,
* 闸门短路径可能 **200** 带 `messages`;冲突 **409**(团队已有对话在整理方案)。
* 前端靠 getCreation / messages?after_seq= 轮询进度,离开页面也不中断 Celery。
*/
async creationSendStream(
creationSend(
id: string,
payload: {
kind?: "text" | "elicit_answer";
@@ -615,50 +616,29 @@ export const api = {
answers?: Record<string, string | string[]>;
model_config_id?: string;
params?: Record<string, string>;
},
onEvent: (evt: { type: string; [k: string]: unknown }) => void,
signal?: AbortSignal
): Promise<void> {
const token = getToken();
const headers = new Headers({ "Content-Type": "application/json", Accept: "text/event-stream" });
if (token) headers.set("Authorization", `Token ${token}`);
const response = await fetch(`${API_BASE}/api/ai/creations/${id}/send/`, {
}
) {
return request<{
conversation_id: string;
agent_status: "idle" | "planning" | "awaiting_user";
messages?: CreationMessage[];
}>(`/api/ai/creations/${id}/send/`, {
method: "POST",
headers,
body: JSON.stringify(payload),
signal
});
if (!response.ok || !response.body) {
const text = await response.text().catch(() => "");
let message = text || "发送失败";
try {
const data = JSON.parse(text) as Record<string, unknown>;
if (typeof data.detail === "string") message = data.detail;
} catch {
/* 非 JSON 错误体,用原文 */
}
throw new ApiError(response.status, message);
}
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let buffer = "";
for (;;) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
let sep: number;
while ((sep = buffer.indexOf("\n\n")) !== -1) {
const frame = buffer.slice(0, sep);
buffer = buffer.slice(sep + 2);
const dataLine = frame.split("\n").find((l) => l.startsWith("data:"));
if (!dataLine) continue;
try {
onEvent(JSON.parse(dataLine.slice(5).trim()));
} catch {
/* 跳过解析失败的帧 */
}
}
}
},
/**
* 终止整理方案(planning)。成功 **200** `{conversation_id, agent_status: idle}`;
* 非 planning **409**。服务端放锁 + Redis 取消标,离开页面再进也生效。
*/
cancelCreationAgent(id: string) {
return request<{
conversation_id: string;
agent_status: "idle" | "planning" | "awaiting_user";
}>(`/api/ai/creations/${id}/cancel/`, {
method: "POST",
body: JSON.stringify({}),
});
},
adoptScript(projectId: string, script_version_id: string) {
return request<ScriptVersion>(`/api/projects/${projectId}/adopt-script/`, {