import "server-only"; import { and, eq } from "drizzle-orm"; import { extractAgentProjectStateFromCanvasData, isAgentProjectRow } from "@/lib/agents/agent-project-compat"; import { appendAgentProjectResultForSave } from "@/lib/agents/agent-project-save-merge"; import { db } from "@/lib/db"; import { canvasProject } from "@/lib/db/schema"; import type { AgentGenerationResultModeType } from "@/types/agent"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; function getCanvasDataRecord(value: unknown) { return value && typeof value === "object" && !Array.isArray(value) ? (value as Record) : {}; } export async function persistAgentProjectGeneratedResult(params: { projectId: string; userId: string; imageUrl: string; modeType: AgentGenerationResultModeType; }) { const projectId = String(params.projectId || "").trim(); const userId = String(params.userId || "").trim(); const imageUrl = String(params.imageUrl || "").trim(); if (!UUID_PATTERN.test(projectId) || !UUID_PATTERN.test(userId) || !/^https?:\/\//i.test(imageUrl)) { return false; } return db.transaction(async (tx) => { const [project] = await tx .select() .from(canvasProject) .where(and(eq(canvasProject.id, projectId), eq(canvasProject.userId, userId))) .limit(1) .for("update"); if (!project || !isAgentProjectRow(project)) { return false; } const nextProjectState = appendAgentProjectResultForSave({ existingState: extractAgentProjectStateFromCanvasData(project.canvasData), modeType: params.modeType, imageUrl, }); const canvasData = getCanvasDataRecord(project.canvasData); const [updatedProject] = await tx .update(canvasProject) .set({ canvasData: { ...canvasData, nodes: Array.isArray(canvasData.nodes) ? canvasData.nodes : [], agentProjectState: nextProjectState, } as unknown as typeof canvasProject.$inferInsert.canvasData, thumbnail: project.thumbnail || imageUrl, workspaceType: "agent", updatedAt: new Date(), }) .where(and(eq(canvasProject.id, projectId), eq(canvasProject.userId, userId))) .returning({ id: canvasProject.id }); return Boolean(updatedProject); }); }