import { prisma, resolvePersona } from "@/lib/db"; import { getOrCreateSettings } from "@/lib/user-settings"; import { getActiveAccountProfile } from "@/lib/account-context"; import { generateContentMatrix } from "@/lib/ai/generate-matrix"; import { parseProviderApiKeys } from "@/lib/ai/keys"; import { parseResearchMap } from "@/lib/types/research"; export async function generateMatrixForScan(scanId: string, count?: number) { const scan = await prisma.scan.findUnique({ where: { id: scanId }, include: { topic: true, items: { where: { OR: [{ qualityTier: null }, { qualityTier: { not: "EXCLUDE" } }] }, orderBy: [{ combinedScore: "desc" }, { score: "desc" }], take: 24, include: { replies: { orderBy: { likeCount: "desc" }, take: 5 }, }, }, }, }); if (!scan) throw new Error("找不到海巡紀錄"); if (scan.items.length === 0) { throw new Error("此海巡沒有素材,請重新海巡"); } const settings = await getOrCreateSettings(); const account = await getActiveAccountProfile(); const apiKeys = parseProviderApiKeys(settings.providerApiKeys); const researchMap = parseResearchMap(scan.topic.researchMap); const rowCount = count ?? settings.matrixRows ?? 7; const rows = await generateContentMatrix({ topicLabel: scan.topic.label, query: scan.topic.query, brief: scan.topic.brief, persona: resolvePersona(settings, account), researchMap, aiProvider: settings.aiProvider, aiModel: settings.aiModel, apiKeys, count: rowCount, posts: scan.items.map((item) => ({ text: item.text, authorName: item.authorName, permalink: item.permalink, searchTag: item.searchTag, likeCount: item.likeCount, replyCount: item.replyCount, qualityReason: item.qualityReason, replies: item.replies.map((r) => ({ text: r.text, authorName: r.authorName, likeCount: r.likeCount, })), })), }); const created = []; for (const row of rows) { const record = await prisma.draft.create({ data: { accountId: scan.topic.accountId, topicId: scan.topicId, text: row.text, angle: row.angle, hook: row.hook, referenceNotes: row.referenceNotes, searchTag: row.searchTag, sortOrder: row.sortOrder, rationale: row.rationale, sources: JSON.stringify(row.sourcePermalinks), status: "PENDING", }, }); created.push(record); } return created; }