First cut

This commit is contained in:
kadil
2026-04-17 16:08:31 -05:00
parent d10105ac00
commit 4ee4cb8e7c
58 changed files with 3243 additions and 1 deletions

152
shared/src/schemas/index.ts Normal file
View File

@@ -0,0 +1,152 @@
import { z } from 'zod';
// ── Site Context ──
export const siteContextSchema = z.object({
businessName: z.string(),
tagline: z.string().optional(),
tone: z.string().default('professional and friendly'),
style: z.string().optional(),
promptContext: z.string().optional(),
primaryColor: z.string().optional(),
contactEmail: z.string().email().optional(),
contactPhone: z.string().optional(),
address: z.string().optional(),
});
export type SiteContext = z.infer<typeof siteContextSchema>;
// ── Section File (union of section types) ──
const baseSectionFields = {
id: z.string(),
order: z.number().int().default(0),
visible: z.boolean().default(true),
image: z.string().optional(),
};
export const heroSectionSchema = z.object({
...baseSectionFields,
type: z.literal('hero'),
headline: z.string(),
subheading: z.string().optional(),
ctaText: z.string().optional(),
ctaLink: z.string().optional(),
});
export const aboutSectionSchema = z.object({
...baseSectionFields,
type: z.literal('about'),
title: z.string().default('About Us'),
content: z.string(),
});
export const featureItemSchema = z.object({
title: z.string(),
description: z.string(),
icon: z.string().optional(),
});
export const featuresSectionSchema = z.object({
...baseSectionFields,
type: z.literal('features'),
title: z.string().default('What We Offer'),
items: z.array(featureItemSchema).min(1),
});
export const testimonialItemSchema = z.object({
quote: z.string(),
author: z.string(),
role: z.string().optional(),
});
export const testimonialsSectionSchema = z.object({
...baseSectionFields,
type: z.literal('testimonials'),
title: z.string().default('What Our Clients Say'),
items: z.array(testimonialItemSchema).min(1),
});
export const textSectionSchema = z.object({
...baseSectionFields,
type: z.literal('text'),
heading: z.string().optional(),
content: z.string(),
});
export const sectionFileSchema = z.discriminatedUnion('type', [
heroSectionSchema,
aboutSectionSchema,
featuresSectionSchema,
testimonialsSectionSchema,
textSectionSchema,
]);
export type SectionFile = z.infer<typeof sectionFileSchema>;
// ── Events ──
export const eventItemSchema = z.object({
id: z.string(),
title: z.string(),
description: z.string().optional(),
date: z.string(),
time: z.string().optional(),
location: z.string().optional(),
});
export const eventsFileSchema = z.object({
events: z.array(eventItemSchema),
});
export type EventsFile = z.infer<typeof eventsFileSchema>;
// ── SMS Sites Config ──
export const smsSiteEntrySchema = z.object({
siteId: z.string(),
phoneNumber: z.string(),
allowedSenders: z.array(z.string()),
repoRoot: z.string().optional(),
});
export const smsSitesConfigSchema = z.object({
sites: z.array(smsSiteEntrySchema),
});
export type SmsSitesConfig = z.infer<typeof smsSitesConfigSchema>;
// ── Edit Request ──
export const editRequestSchema = z.object({
message: z.string().min(1),
repo_relative_path: z.string().optional(),
proposal_id: z.string().optional(),
confirm: z.enum(['yes', 'no']).optional(),
});
export type EditRequest = z.infer<typeof editRequestSchema>;
export const editJobPayloadSchema = z.discriminatedUnion('kind', [
z.object({
kind: z.literal('propose'),
id: z.string(),
message: z.string(),
repo_relative_path: z.string().optional(),
source: z.enum(['sms', 'http', 'editor']).default('http'),
smsReplyMeta: z.object({
from: z.string(),
to: z.string(),
}).optional(),
}),
z.object({
kind: z.literal('apply'),
id: z.string(),
proposal_id: z.string(),
source: z.enum(['sms', 'http', 'editor']).default('http'),
smsReplyMeta: z.object({
from: z.string(),
to: z.string(),
}).optional(),
}),
]);
export type EditJobPayload = z.infer<typeof editJobPayloadSchema>;
// ── Routing output (LLM structured output) ──
export const routingOutputSchema = z.object({
repo_relative_path: z.string(),
needs_clarification: z.boolean().default(false),
reason: z.string(),
clarification_message: z.string().optional(),
});
export type RoutingOutput = z.infer<typeof routingOutputSchema>;