66 lines
3.0 KiB
TypeScript
66 lines
3.0 KiB
TypeScript
import type { UIMessageChunk } from "ai";
|
||
|
||
export type BackendSseEvent = {
|
||
event: string;
|
||
data: Record<string, unknown>;
|
||
};
|
||
|
||
export function backendEventToUiChunk(
|
||
item: BackendSseEvent,
|
||
textId: string,
|
||
): UIMessageChunk | null {
|
||
if (item.event === "text_delta") {
|
||
return { type: "text-delta", id: textId, delta: String(item.data.text || "") };
|
||
}
|
||
if (item.event === "progress") {
|
||
return {
|
||
type: "data-cad-progress",
|
||
id: `progress_${String(item.data.step || Date.now())}`,
|
||
data: item.data,
|
||
};
|
||
}
|
||
if (["requirements_document", "completion_checklist", "completion_audit", "agent_thinking", "tool_call", "candidate_result", "candidate_review", "geometry_diagnostic", "geometry_conclusion", "step_review", "checkpoint", "rollback", "final_review", "task_terminal"].includes(item.event)) {
|
||
const review = item.data.review && typeof item.data.review === "object"
|
||
? item.data.review as Record<string, unknown>
|
||
: null;
|
||
const status = item.event === "task_terminal"
|
||
? (String(item.data.lifecycle || "") === "failed" ? "error" : "success")
|
||
: (item.event === "candidate_review" && String(review?.verdict || "") === "reject")
|
||
|| (item.event === "final_review" && String(review?.verdict || "") === "repair" && Number(review?.confidence || 0) >= 0.85)
|
||
? "error"
|
||
: String(item.data.status || "running");
|
||
return {
|
||
type: "data-cad-progress",
|
||
id: `${item.event}_${String(item.data.taskId || Date.now())}_${String(item.data.nodeId || "")}`,
|
||
data: { step: item.event, label: ({
|
||
requirements_document: "冻结需求", completion_checklist: "完成清单", completion_audit: "完成审计", agent_thinking: "建模判断", tool_call: "建模工具", candidate_result: "候选构建", candidate_review: "候选独立复核", geometry_diagnostic: "几何诊断", geometry_conclusion: "几何结论", step_review: "步骤审查", checkpoint: "构建检查点", rollback: "回滚检查点", final_review: "最终视觉复核", task_terminal: "生成任务",
|
||
} as Record<string, string>)[item.event], status, message: String(
|
||
item.data.message || item.data.reason || (review?.evidence instanceof Array ? review.evidence.join(";") : ""),
|
||
),
|
||
...(item.data.taskId ? { taskId: String(item.data.taskId) } : {}),
|
||
...(item.data.nodeId ? { nodeId: String(item.data.nodeId) } : {}),
|
||
...(item.data.lifecycle ? { lifecycle: String(item.data.lifecycle) } : {}),
|
||
},
|
||
};
|
||
}
|
||
if (item.event === "cad_result") {
|
||
const taskId = String(item.data.taskId || "");
|
||
const revisionId = String(item.data.revisionId || Date.now());
|
||
return {
|
||
type: "data-cad-result",
|
||
// Each revision is a distinct progressive result. Reusing only the task
|
||
// id makes the AI SDK reconcile intermediate revisions into one part.
|
||
id: `result_${taskId}_${revisionId}`,
|
||
data: item.data,
|
||
};
|
||
}
|
||
if (item.event === "cad_error") {
|
||
return {
|
||
type: "data-cad-error",
|
||
id: `error_${Date.now()}`,
|
||
data: item.data,
|
||
};
|
||
}
|
||
return null;
|
||
}
|