feat: 搭建阶段 0 与阶段 1 基础工程
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import {
|
||||
confidenceLevels,
|
||||
evidenceSourceTypes,
|
||||
executionStatuses,
|
||||
platforms,
|
||||
reportableTaskStatuses,
|
||||
sampleFlags
|
||||
} from "@cross-ai/domain";
|
||||
import { z } from "zod";
|
||||
|
||||
export const SourceScopeSchema = z.object({
|
||||
platforms: z.array(z.enum(platforms)).min(1),
|
||||
link_count: z.number().int().nonnegative(),
|
||||
review_count: z.number().int().nonnegative()
|
||||
});
|
||||
|
||||
export const InsightCardSchema = z
|
||||
.object({
|
||||
card_id: z.string().min(1),
|
||||
title: z.string().min(1),
|
||||
statement: z.string().min(1),
|
||||
confidence: z.enum(confidenceLevels),
|
||||
sample_flag: z.enum(sampleFlags),
|
||||
source_scope: SourceScopeSchema,
|
||||
evidence_ids: z.array(z.string().min(1))
|
||||
})
|
||||
.superRefine((value, ctx) => {
|
||||
if (value.sample_flag !== "insufficient" && value.evidence_ids.length === 0) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Non-insufficient insights must include evidence_ids.",
|
||||
path: ["evidence_ids"]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export const EvidenceSchema = z.object({
|
||||
evidence_id: z.string().min(1),
|
||||
platform: z.enum(platforms),
|
||||
source_type: z.enum(evidenceSourceTypes),
|
||||
source_url: z.string().url(),
|
||||
review_ref: z.string().nullable(),
|
||||
snippet: z.string().min(1),
|
||||
captured_at: z.string().datetime()
|
||||
});
|
||||
|
||||
export const PlatformInsightSchema = z.object({
|
||||
platform: z.enum(platforms),
|
||||
execution_status: z.enum(executionStatuses),
|
||||
selected_link_count: z.number().int().nonnegative(),
|
||||
price_range: z
|
||||
.object({
|
||||
min: z.number().nonnegative(),
|
||||
max: z.number().nonnegative()
|
||||
})
|
||||
.nullable(),
|
||||
selling_points: z.array(InsightCardSchema),
|
||||
positive_themes: z.array(InsightCardSchema),
|
||||
negative_themes: z.array(InsightCardSchema),
|
||||
store_diff_notes: z.array(InsightCardSchema)
|
||||
});
|
||||
|
||||
export const ReportSchema = z.object({
|
||||
report_id: z.string().min(1),
|
||||
report_version: z.number().int().positive(),
|
||||
task_id: z.string().min(1),
|
||||
generated_at: z.string().datetime(),
|
||||
task_status: z.enum(reportableTaskStatuses),
|
||||
summary: z.object({
|
||||
headline: z.string().min(1),
|
||||
key_points: z.array(z.string().min(1)).min(1),
|
||||
limitations: z.array(z.string().min(1))
|
||||
}),
|
||||
product_snapshot: z.object({
|
||||
query: z.string().min(1),
|
||||
normalized_product_name: z.string().min(1),
|
||||
platform_count: z.number().int().nonnegative(),
|
||||
selected_link_count: z.number().int().nonnegative(),
|
||||
review_sample_count: z.number().int().nonnegative(),
|
||||
analysis_time_range: z.object({
|
||||
start: z.string().datetime(),
|
||||
end: z.string().datetime()
|
||||
})
|
||||
}),
|
||||
platform_insights: z.array(PlatformInsightSchema),
|
||||
cross_platform_insights: z.array(InsightCardSchema),
|
||||
recommendations: z.array(InsightCardSchema),
|
||||
evidence_index: z.array(EvidenceSchema),
|
||||
quality_flags: z.object({
|
||||
sample_insufficient: z.boolean(),
|
||||
partial_platform_failure: z.boolean(),
|
||||
blocked_platforms: z.array(z.enum(platforms)),
|
||||
failed_platforms: z.array(z.enum(platforms))
|
||||
})
|
||||
});
|
||||
|
||||
export type ReportSnapshot = z.infer<typeof ReportSchema>;
|
||||
|
||||
export function parseReportSnapshot(input: unknown): ReportSnapshot {
|
||||
return ReportSchema.parse(input);
|
||||
}
|
||||
Reference in New Issue
Block a user