import { ZodError } from "zod"; import { canApplyCanvasAgentMutations, type CanvasAgentFeatureFlags, } from "@/lib/canvas/agent-feature-flags"; import { CanvasAgentMutationError, type CanvasOperationResult, } from "@/lib/canvas/agent-mutations"; import { parseCanvasAgentOperationRequestBody } from "@/lib/canvas/agent-operation-request"; import type { CanvasOperationPlan } from "@/types/canvas/agent-protocol"; export type CanvasAgentOperationRouteBody = | { success: true; data: CanvasOperationResult; } | { success: false; error: string; code?: string; writebackMode?: CanvasAgentFeatureFlags["writebackMode"]; details?: unknown; }; export type CanvasAgentOperationRouteResponse = { status: number; body: CanvasAgentOperationRouteBody; }; export async function handleCanvasAgentOperationRouteRequest(params: { userId?: string | null; projectId: string; rawBody?: unknown; readBody?: () => Promise; features: CanvasAgentFeatureFlags; applyOperation: (input: { userId: string; projectId: string; plan: CanvasOperationPlan; }) => Promise; logger?: Pick; }): Promise { const userId = String(params.userId || "").trim(); if (!userId) { return { status: 401, body: { success: false, error: "未登录" }, }; } if (!canApplyCanvasAgentMutations(params.features)) { return { status: 409, body: { success: false, error: "当前画布 Agent 写回处于灰度保护,未修改画布", code: "CANVAS_AGENT_WRITEBACK_DISABLED", writebackMode: params.features.writebackMode, }, }; } try { const rawBody = params.readBody ? await params.readBody() : params.rawBody; const body = parseCanvasAgentOperationRequestBody(rawBody); const planProjectId = String(body.operationPlan.projectId || "").trim(); if (planProjectId && planProjectId !== params.projectId) { return { status: 400, body: { success: false, error: "operation projectId 与请求项目不一致", code: "CANVAS_AGENT_PROJECT_MISMATCH", }, }; } const operationPlan: CanvasOperationPlan = { ...body.operationPlan, projectId: planProjectId || params.projectId, }; const result = await params.applyOperation({ userId, projectId: params.projectId, plan: operationPlan, }); return { status: 200, body: { success: true, data: result, }, }; } catch (error) { if (error instanceof CanvasAgentMutationError) { return { status: error.status, body: { success: false, error: error.message, code: error.code, }, }; } if (error instanceof ZodError) { return { status: 400, body: { success: false, error: "请求参数无效", details: error.flatten(), }, }; } if (error instanceof SyntaxError) { return { status: 400, body: { success: false, error: "请求 JSON 无效" }, }; } params.logger?.error("[CanvasAgentOperations] apply operation failed:", error); return { status: 500, body: { success: false, error: "执行画布操作失败" }, }; } }