import { NextResponse } from "next/server"; import { z } from "zod"; import { auth } from "@/app/(auth)/auth"; import { getChatById, getSystemSetting } from "@/lib/db/queries"; import { buildClawdCancelKey, cancelClawdRequest, } from "@/lib/openclaw-chat/cancel-registry"; import { OPENCLAW_AUTH_REQUIRED_CODE, OPENCLAW_AUTH_REQUIRED_MESSAGE, } from "@/lib/openclaw-chat/errors"; import { normalizeOpenClawChatConfig, OPENCLAW_CHAT_CONFIG_KEY, } from "@/lib/openclaw-chat/config"; import { deletePersistedClawdTask, getPersistedClawdTask, } from "@/lib/openclaw-chat/task-store"; import { getPersistedUpstreamTaskState, stopOpenClawDurableTask, } from "@/lib/openclaw-chat/upstream-task-client"; const cancelSchema = z.object({ id: z.string().uuid(), userMessageId: z.string().uuid(), }); export async function POST(request: Request) { const session = await auth().catch(() => null); if (!session?.user?.id) { return NextResponse.json( { error: OPENCLAW_AUTH_REQUIRED_MESSAGE, code: OPENCLAW_AUTH_REQUIRED_CODE, }, { status: 401 } ); } const parsed = cancelSchema.safeParse(await request.json().catch(() => null)); if (!parsed.success) { return NextResponse.json({ error: "请求参数不正确" }, { status: 400 }); } const existingChat = await getChatById({ id: parsed.data.id }).catch(() => null); if (existingChat && existingChat.userId !== session.user.id) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } const cancelKey = buildClawdCancelKey({ userId: session.user.id, chatId: parsed.data.id, userMessageId: parsed.data.userMessageId, }); const task = await getPersistedClawdTask({ chatId: parsed.data.id, userMessageId: parsed.data.userMessageId, }).catch(() => null); const active = cancelClawdRequest(cancelKey); const upstreamTask = task ? getPersistedUpstreamTaskState(task.metadata) : null; if (upstreamTask) { const setting = await getSystemSetting({ key: OPENCLAW_CHAT_CONFIG_KEY, }).catch(() => null); const config = normalizeOpenClawChatConfig(setting?.value); if (config.enabled && config.baseUrl && config.token) { await stopOpenClawDurableTask({ config, upstreamTask }).catch((error) => { console.warn("[ClawdChat Cancel] Upstream stop deferred:", { chatId: parsed.data.id, taskId: upstreamTask.taskId, error, }); }); } } const deleted = await deletePersistedClawdTask({ chatId: parsed.data.id, userMessageId: parsed.data.userMessageId, }).catch(() => []); return NextResponse.json({ canceled: true, active, deleted: deleted.length > 0, }); }