From 63509dba207fa7449da12e9010a32f55237d5d5e Mon Sep 17 00:00:00 2001 From: czj <13261895355@163.com> Date: Wed, 8 Jul 2026 23:40:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E4=BA=BA=E5=91=B3=E6=96=87?= =?UTF-8?q?=E6=A1=88=E7=A9=BA=E8=AF=81=E6=8D=AE=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/domain/__tests__/validation.test.ts | 18 ++++++++++++++++++ src/lib/domain/validation.ts | 10 +++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lib/domain/__tests__/validation.test.ts b/src/lib/domain/__tests__/validation.test.ts index c645177..cc069c4 100644 --- a/src/lib/domain/__tests__/validation.test.ts +++ b/src/lib/domain/__tests__/validation.test.ts @@ -122,6 +122,24 @@ describe("domain validation", () => { expect(parsed.ai_taste_checks[0]?.rule_id).toBe("promotion_tone"); }); + it("normalizes empty AI taste check evidence from LLM copy results", () => { + const parsed = copyOptimizationResultSchema.parse({ + optimized_text: "我把句子顺了一下。", + change_notes: [], + ai_taste_checks: [ + { + rule_id: "promotion_tone", + status: "pass", + evidence: "", + suggestion: "", + }, + ], + warnings: [], + }); + + expect(parsed.ai_taste_checks[0]?.evidence).toBe("未提供具体证据。"); + }); + it("accepts an unconfirmed optimization fact card with unresolved items", () => { const parsed = optimizationFactCardSchema.parse({ company_full_name: "", diff --git a/src/lib/domain/validation.ts b/src/lib/domain/validation.ts index c4198b1..8105c3a 100644 --- a/src/lib/domain/validation.ts +++ b/src/lib/domain/validation.ts @@ -217,6 +217,14 @@ const optionalLlmStringSchema = z.preprocess((value) => { return normalizeStringValue(value); }, z.string().trim().default("")); +const fallbackLlmEvidenceSchema = z.preprocess((value) => { + const normalized = normalizeStringValue(value); + if (typeof normalized === "string" && normalized.trim().length === 0) { + return "未提供具体证据。"; + } + return normalized; +}, z.string().trim().min(1)); + const stringListSchema = z.preprocess( normalizeStringList, z.array(z.string().trim().min(1)).default([]), @@ -480,7 +488,7 @@ const copyAiTasteCheckSchema = z.object({ "filler_hedging", ]), status: z.enum(["pass", "warn"]), - evidence: requiredLlmStringSchema, + evidence: fallbackLlmEvidenceSchema, suggestion: optionalLlmStringSchema, }) satisfies z.ZodType;