Fix audit generation and enrichment fallback

This commit is contained in:
2026-06-07 23:03:57 +02:00
parent e9463e8ef2
commit 470fb0f348
10 changed files with 2190 additions and 138 deletions

View File

@@ -68,13 +68,14 @@ const ENGLISH_MARKERS = new Set([
const OBSERVATION_TOKENS = [
/\b(mir|ich)\b[^\n]{0,80}\b(aufgefallen|festgestellt|bemerkt|beobachtet|gesehen|sichtbar)\b/i,
/\b(erkennt|zeigt|sichtbar|feststell|finde|fällt)\b/i,
/\b(erkennt|zeigt|sichtbar|festgestellt|feststellen|feststellbar|finde|fällt)\b/i,
/\b(ich sehe|ich habe gesehen|bei der Prüfung)\b/i,
];
const SUGGESTION_TOKENS = [
/\b(empfehle|empfiehlt|vorschlage|vorschlagen|schlage vor|könnte helfen|kannst|können wir|sollte|sollten|ich könnte|ich würde|ich empfehle)\b/i,
/\b(schlage vor|schlage)\b/i,
/\b(?:mein(?:e[rmns]?)?\s+)?(?:konkreter\s+)?vorschlag(?:\s+ist)?\b/i,
/\b(ergänzt|ergänzen|anpassen|optimieren|verbessern|prüfen|einbauen|einzusetzen|setzten)\b/i,
];
@@ -386,7 +387,7 @@ export function validateCallScriptCopy(script: CallScriptCopy): GermanCopyGuardR
requireIchForm: true,
});
validateCallScriptText(issues, "callScript.closeLine", script.closeLine, {
requireIchForm: true,
requireIchForm: false,
});
script.callScript.forEach((line, index) => {

View File

@@ -1,16 +1,47 @@
import { z } from "zod";
export const findingItemSchema = z.object({
const nonEmptyTextSchema = z.string().trim().min(1);
export const legacyFindingItemSchema = z.object({
section: z.string(),
finding: z.string(),
suggestion: z.string(),
});
export const v3FindingItemSchema = z.object({
skill_id: nonEmptyTextSchema,
observation: nonEmptyTextSchema,
customer_benefit: nonEmptyTextSchema,
public_phrasing: nonEmptyTextSchema,
severity: z.union([z.literal(1), z.literal(2), z.literal(3)]),
evidence: nonEmptyTextSchema,
applies: z.boolean(),
});
export const findingItemSchema = legacyFindingItemSchema;
export const internalFindingsSchema = z.object({
findings: z.array(findingItemSchema),
summary: z.string(),
});
export const auditClassificationSchema = z.object({
findings: z.array(v3FindingItemSchema).min(1),
summary: nonEmptyTextSchema,
usedSkills: z.array(nonEmptyTextSchema).nullable(),
});
export const auditGenerationResultSchema = z.object({
findings: z.array(v3FindingItemSchema).min(1),
usedSkills: z.array(nonEmptyTextSchema).min(1),
publicAuditText: nonEmptyTextSchema,
finalSummary: nonEmptyTextSchema,
emailSubject: nonEmptyTextSchema,
emailBody: nonEmptyTextSchema,
phoneScript: nonEmptyTextSchema,
ctaType: z.enum(["anruf", "termin", "rueckruf"]),
});
export const auditSummarySchema = z.object({
summary: z.string(),
keyFindings: z.array(z.string()),
@@ -36,19 +67,22 @@ export const callScriptSchema = z.object({
export const followUpDraftSchema = z.object({
message: z.string(),
followInDays: z.number().int().min(0).optional(),
goals: z.array(z.string()).optional(),
followInDays: z.number().int().min(0).nullable(),
goals: z.array(z.string()).nullable(),
});
export const qualityReviewSchema = z.object({
isValid: z.boolean(),
issues: z.array(z.string()),
suggestions: z.array(z.string()),
notes: z.array(z.string()).optional(),
notes: z.array(z.string()).nullable(),
});
export type FindingItem = z.infer<typeof findingItemSchema>;
export type V3FindingItem = z.infer<typeof v3FindingItemSchema>;
export type InternalFindings = z.infer<typeof internalFindingsSchema>;
export type AuditClassification = z.infer<typeof auditClassificationSchema>;
export type AuditGenerationResult = z.infer<typeof auditGenerationResultSchema>;
export type AuditSummary = z.infer<typeof auditSummarySchema>;
export type PublicAuditText = z.infer<typeof publicAuditTextSchema>;
export type EmailDraft = z.infer<typeof emailDraftSchema>;