since3-portal/modules/templates/ai/schemas.ts
2026-10-05 08:23:02 +02:00

77 lines
2.6 KiB
TypeScript

import * as z from "zod"
export const AccessSchema = z.union([
z.object({ token: z.string().regex(/^[A-Za-z0-9_-]{20,64}$/) }),
z.object({ variantId: z.string().uuid() }),
])
export type AiAccess = z.infer<typeof AccessSchema>
export const ChatRequestSchema = z.object({
access: AccessSchema,
mode: z.enum(["chat", "phone"]),
messages: z
.array(z.object({ role: z.enum(["user", "assistant"]), content: z.string().trim().min(1).max(2000) }))
.min(1)
.max(40),
})
export const CHANNELS = { instagram: "Instagram", facebook: "Facebook", linkedin: "LinkedIn", google: "Google Ads" } as const
export type Channel = keyof typeof CHANNELS
export const TONES = ["Locker", "Professionell", "Emotional", "Witzig"] as const
export type Tone = (typeof TONES)[number]
export const GenerateRequestSchema = z.discriminatedUnion("task", [
z.object({ task: z.literal("email"), access: AccessSchema, inquiry: z.string().trim().min(10).max(4000) }),
z.object({ task: z.literal("quote"), access: AccessSchema, inquiry: z.string().trim().min(10).max(4000) }),
z.object({
task: z.literal("content"),
access: AccessSchema,
topic: z.string().trim().min(3).max(500),
channel: z.enum(["instagram", "facebook", "linkedin", "google"]),
tone: z.enum(TONES),
}),
])
export const BookingSchema = z.object({
art: z.string(),
name: z.string(),
kontakt: z.string(),
datum: z.string().optional(),
uhrzeit: z.string().optional(),
personen: z.string().optional(),
anliegen: z.string().optional(),
})
export type Booking = z.infer<typeof BookingSchema>
export const QuoteSchema = z.object({
betreff: z.string(),
anrede: z.string(),
einleitung: z.string(),
positionen: z.array(
z.object({ titel: z.string(), beschreibung: z.string(), menge: z.number(), einheit: z.string(), einzelpreis: z.number() })
),
hinweise: z.array(z.string()),
rueckfragen: z.array(z.string()),
gueltig_tage: z.number(),
abschluss: z.string(),
})
export type Quote = z.infer<typeof QuoteSchema>
export const ContentSchema = z.object({
varianten: z.array(
z.object({ hook: z.string(), text: z.string(), hashtags: z.array(z.string()), cta: z.string(), bildidee: z.string() })
),
})
export type ContentResult = z.infer<typeof ContentSchema>
// Zeilenweise JSON (NDJSON) von /api/ai/chat und /api/ai/generate (E-Mail)
export type AiEvent =
| { type: "text"; text: string }
| { type: "booking"; data: Booking }
| { type: "error"; message: string }
| { type: "done" }