haixunMaster/app/api/optimize/route.ts

91 lines
2.6 KiB
TypeScript

import { NextResponse } from "next/server";
import { prisma, resolvePersona } from "@/lib/db";
import { getActiveAccountProfile } from "@/lib/account-context";
import { getOrCreateSettings } from "@/lib/user-settings";
import { optimizePost, type OptimizeMode } from "@/lib/ai/optimize-post";
import { parseProviderApiKeys } from "@/lib/ai/keys";
import { THREADS_MAX_CHARS } from "@/lib/utils";
import { trackAiTask } from "@/lib/jobs/track";
export const maxDuration = 60;
const VALID_MODES: OptimizeMode[] = ["polish", "hook", "shorter", "engaging", "custom"];
export async function POST(request: Request) {
try {
const body = await request.json();
const {
draftId,
text,
mode = "polish",
instruction,
save = false,
} = body as {
draftId?: string;
text?: string;
mode?: OptimizeMode;
instruction?: string;
save?: boolean;
};
if (!VALID_MODES.includes(mode)) {
return NextResponse.json({ error: "無效的優化模式" }, { status: 400 });
}
let sourceText = text?.trim();
let angle: string | null | undefined;
let draftRecord = null;
if (draftId) {
draftRecord = await prisma.draft.findUnique({ where: { id: draftId } });
if (!draftRecord) {
return NextResponse.json({ error: "找不到草稿" }, { status: 404 });
}
sourceText = sourceText || draftRecord.text;
angle = draftRecord.angle;
}
if (!sourceText) {
return NextResponse.json({ error: "缺少貼文內容" }, { status: 400 });
}
if (sourceText.length > THREADS_MAX_CHARS) {
return NextResponse.json({ error: `原文超過 ${THREADS_MAX_CHARS} 字上限` }, { status: 400 });
}
const settings = await getOrCreateSettings();
const account = await getActiveAccountProfile();
const apiKeys = parseProviderApiKeys(settings.providerApiKeys);
const result = await trackAiTask("AI 優化貼文", () => optimizePost({
text: sourceText,
mode,
instruction,
persona: resolvePersona(settings, account),
angle,
aiProvider: settings.aiProvider,
aiModel: settings.aiModel,
apiKeys,
}));
if (save && draftRecord) {
await prisma.draft.update({
where: { id: draftRecord.id },
data: {
text: result.text,
status: "EDITED",
},
});
}
return NextResponse.json({
text: result.text,
summary: result.summary,
saved: save && !!draftRecord,
});
} catch (error) {
const message = error instanceof Error ? error.message : "AI 優化失敗";
return NextResponse.json({ error: message }, { status: 500 });
}
}