feat: add consultation and product domain registries
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
runConsultationWorkflow,
|
||||
} from "@/mastra";
|
||||
import { blocksPromptExtraction } from "@/lib/consult-safety";
|
||||
import { consultationDomainSchema } from "@/lib/consultation-domain-registry";
|
||||
import { parseAgentReply } from "@/lib/agent-reply";
|
||||
import {
|
||||
consultationEntrypointSchema,
|
||||
@@ -70,7 +71,7 @@ const generalChatRequestSchema = z.object({
|
||||
...chatRequestMetadataSchema.shape,
|
||||
consultationMode: z.literal("general_no_birth_time"),
|
||||
question: z.string().trim().min(1).max(500),
|
||||
theme: z.enum(["career", "marriage", "wealth", "timing", "general"]),
|
||||
theme: consultationDomainSchema,
|
||||
entrypoint: z.undefined().optional(),
|
||||
}).strict();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { RECTIFICATION_SKILL_NAME, RECTIFICATION_SKILL_VERSION } from "@/lib/rec
|
||||
import { blocksPromptExtraction } from "@/lib/consult-safety";
|
||||
import { authorizeUsage, completeUsage, releaseUsage } from "@/lib/consultation-billing";
|
||||
import { loadRuntimeFeatureFlags } from "@/lib/feature-flags";
|
||||
import { isProductEnabled } from "@/lib/product-access";
|
||||
import { resolveSessionLanguageModel } from "@/lib/model-catalog";
|
||||
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
@@ -81,6 +82,13 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
if (!await isProductEnabled("rectification")) {
|
||||
return NextResponse.json(
|
||||
{ error: "生时校正服务暂未开放", code: "rectification_product_disabled" },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const parsed = agentRequestSchema.safeParse(await request.json().catch(() => null));
|
||||
if (!parsed.success) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
|
||||
import { isProductEnabled } from "@/lib/product-access";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
import { RectificationToolServiceError } from "@/lib/rectification-agentic/v9/tool-service";
|
||||
|
||||
@@ -63,6 +64,13 @@ export async function POST(request: Request, context: RouteContext) {
|
||||
return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
if (!await isProductEnabled("rectification")) {
|
||||
return NextResponse.json(
|
||||
{ error: "生时校正服务暂未开放", code: "rectification_product_disabled" },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const { caseId } = await context.params;
|
||||
if (!z.string().uuid().safeParse(caseId).success) {
|
||||
return NextResponse.json({ error: "请求内容不正确", code: "invalid_case_id" }, { status: 400 });
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
|
||||
import { isProductEnabled } from "@/lib/product-access";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
import {
|
||||
RectificationCaseServiceError,
|
||||
@@ -47,6 +48,13 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
}
|
||||
|
||||
if (!await isProductEnabled("rectification")) {
|
||||
return NextResponse.json(
|
||||
{ error: "生时校正服务暂未开放", code: "rectification_product_disabled" },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const parsed = parseOpenRectificationCaseRequest(
|
||||
await request.json().catch(() => null),
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
resolveSkillSnapshot,
|
||||
} from "@/lib/personal-report-generation";
|
||||
import { REPORT_STABLE_CODES } from "@/lib/personal-report-codes";
|
||||
import { isProductEnabled } from "@/lib/product-access";
|
||||
import {
|
||||
isPersonalReportFeatureEnabled,
|
||||
readPersonalReportDailyLimit,
|
||||
@@ -107,6 +108,9 @@ export async function POST(request: Request) {
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
||||
const userId = authError || !user ? null : user.id;
|
||||
const reportProductEnabled = userId
|
||||
? await isProductEnabled("report_center")
|
||||
: false;
|
||||
|
||||
// Admin client (service_role / self-hosted admin DB): generation writes
|
||||
// and counting. The authenticated client is forbidden by migration grants
|
||||
@@ -157,7 +161,7 @@ export async function POST(request: Request) {
|
||||
if (error) throw error;
|
||||
return Boolean(data);
|
||||
},
|
||||
featureEnabled: isPersonalReportFeatureEnabled(process.env),
|
||||
featureEnabled: reportProductEnabled && isPersonalReportFeatureEnabled(process.env),
|
||||
dailyLimit: readPersonalReportDailyLimit(process.env),
|
||||
counts: {
|
||||
countGenerating: async () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { isProductEnabled } from "@/lib/product-access";
|
||||
import { isSupabaseConfigurationError } from "@/lib/supabase/config";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
|
||||
@@ -17,6 +18,12 @@ export async function GET() {
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
if (!await isProductEnabled("compatibility")) {
|
||||
return NextResponse.json(
|
||||
{ error: "合盘服务暂未开放", code: "compatibility_product_disabled" },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from("synastry_reports")
|
||||
@@ -37,15 +44,21 @@ export async function GET() {
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
if (!await isProductEnabled("compatibility")) {
|
||||
return NextResponse.json(
|
||||
{ error: "合盘服务暂未开放", code: "compatibility_product_disabled" },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const body = await request.json().catch(() => null) as SynastryReportPayload | null;
|
||||
if (!body?.report || typeof body.report !== "object" || Array.isArray(body.report)) {
|
||||
return NextResponse.json({ error: "合盘报告格式不正确" }, { status: 400 });
|
||||
}
|
||||
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
|
||||
const partnerName = body.partnerName?.trim() || "对方";
|
||||
const record = {
|
||||
...(body.id ? { id: body.id } : {}),
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { isProductEnabled } from "@/lib/product-access";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
import {
|
||||
synastryBirthPayload,
|
||||
type GlobalBirthProfile as Profile,
|
||||
@@ -116,6 +118,18 @@ async function postPython(path: string, body: unknown) {
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const supabase = await createServerSupabaseClient();
|
||||
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
}
|
||||
if (!await isProductEnabled("compatibility")) {
|
||||
return NextResponse.json(
|
||||
{ error: "合盘服务暂未开放", code: "compatibility_product_disabled" },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const body = await request.json().catch(() => null) as { selfProfile?: Profile; partnerProfile?: Profile; relationshipType?: RelationshipType } | null;
|
||||
if (!body?.selfProfile || !body.partnerProfile) {
|
||||
return NextResponse.json({ error: "请提供双方星盘资料" }, { status: 400 });
|
||||
|
||||
Reference in New Issue
Block a user