优化全能创作
This commit is contained in:
+24
-44
@@ -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/`, {
|
||||
|
||||
Reference in New Issue
Block a user