2026-01-11 12:35:53 +08:00
|
|
|
import { NextResponse } from "next/server";
|
|
|
|
|
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
2026-01-17 10:12:53 +08:00
|
|
|
import { isConvexEnabled } from "@/lib/convex/enabled";
|
|
|
|
|
import { requireAuthContext } from "@/lib/auth/authContext";
|
2026-01-11 12:35:53 +08:00
|
|
|
import {
|
|
|
|
|
buildClientToolKey,
|
|
|
|
|
resolveClientToolCall,
|
|
|
|
|
type ClientToolResult,
|
|
|
|
|
} from "@/lib/ai-agent/runtime/clientToolBridge";
|
|
|
|
|
|
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
|
|
|
|
|
|
type Payload = {
|
|
|
|
|
requestId: string;
|
|
|
|
|
callId: string;
|
|
|
|
|
ok: boolean;
|
|
|
|
|
result?: unknown;
|
|
|
|
|
error?: string;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export async function POST(request: Request) {
|
|
|
|
|
const payload = (await request.json().catch(() => null)) as Payload | null;
|
|
|
|
|
if (!payload) return NextResponse.json({ error: "缺少请求体" }, { status: 400 });
|
|
|
|
|
|
|
|
|
|
const requestId = String(payload.requestId ?? "").trim();
|
|
|
|
|
const callId = String(payload.callId ?? "").trim();
|
|
|
|
|
if (!requestId || !callId) {
|
|
|
|
|
return NextResponse.json({ error: "缺少 requestId/callId" }, { status: 400 });
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-17 10:12:53 +08:00
|
|
|
const userId = (() => {
|
|
|
|
|
if (isConvexEnabled()) {
|
|
|
|
|
const auth = requireAuthContext();
|
|
|
|
|
return auth.userId;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
const resolvedUserId = async () => {
|
|
|
|
|
if (userId) return userId;
|
|
|
|
|
const supabase = await createSupabaseRouteClient();
|
|
|
|
|
const {
|
|
|
|
|
data: { session },
|
|
|
|
|
} = await supabase.auth.getSession();
|
|
|
|
|
if (!session) return null;
|
|
|
|
|
return session.user.id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const finalUserId = await resolvedUserId();
|
|
|
|
|
if (!finalUserId) return NextResponse.json({ error: "未登录" }, { status: 401 });
|
2026-01-11 12:35:53 +08:00
|
|
|
|
|
|
|
|
const result: ClientToolResult = payload.ok
|
|
|
|
|
? { ok: true, result: "result" in payload ? payload.result : null }
|
|
|
|
|
: { ok: false, error: String(payload.error ?? "客户端工具执行失败") };
|
|
|
|
|
|
|
|
|
|
const key = buildClientToolKey(requestId, callId);
|
|
|
|
|
const resolved = resolveClientToolCall({
|
|
|
|
|
key,
|
2026-01-17 10:12:53 +08:00
|
|
|
userId: finalUserId,
|
2026-01-11 12:35:53 +08:00
|
|
|
result,
|
|
|
|
|
});
|
|
|
|
|
if (!resolved.ok) {
|
|
|
|
|
return NextResponse.json({ error: resolved.error }, { status: 404 });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NextResponse.json({ ok: true });
|
|
|
|
|
}
|