| import type { InterviewTemplate, InterviewItem, InterviewHandoff } from './types'; |
|
|
| export interface ItemForm { question: string; criteria: string; required: boolean; } |
| export interface TemplateForm { |
| title: string; |
| description: string; |
| artifactPath: string; |
| items: ItemForm[]; |
| handoff: { label: string; prompt: string; mode: 'code' | 'chat' } | null; |
| } |
|
|
| |
| export function slugify(name: string): string { |
| return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); |
| } |
|
|
| export function emptyForm(): TemplateForm { |
| return { |
| title: '', |
| description: '', |
| artifactPath: '/.interviews/untitled.md', |
| items: [{ question: '', criteria: '', required: true }], |
| handoff: null, |
| }; |
| } |
|
|
| export function templateToForm(t: InterviewTemplate): TemplateForm { |
| return { |
| title: t.title, |
| description: t.description, |
| artifactPath: t.artifacts[0]?.path ?? '/.interviews/untitled.md', |
| items: t.items.map(i => ({ |
| question: i.elicit, |
| criteria: i.completion.find(a => a.type === 'judge')?.criteria ?? '', |
| required: i.required !== false, |
| })), |
| handoff: t.handoff ? { label: t.handoff.label, prompt: t.handoff.prompt, mode: t.handoff.mode } : null, |
| }; |
| } |
|
|
| export function formToTemplate(f: TemplateForm, id: string): InterviewTemplate { |
| const items: InterviewItem[] = f.items.map(i => ({ |
| id: slugify(i.question) || 'item', |
| elicit: i.question.trim(), |
| required: i.required, |
| completion: [{ type: 'judge' as const, criteria: i.criteria.trim(), description: i.question.trim() }], |
| })); |
| const handoff: InterviewHandoff | undefined = f.handoff && f.handoff.label.trim() |
| ? { label: f.handoff.label.trim(), prompt: f.handoff.prompt.trim(), mode: f.handoff.mode } |
| : undefined; |
| return { |
| id, |
| title: f.title.trim(), |
| description: f.description.trim(), |
| artifacts: [{ path: f.artifactPath.trim() }], |
| items, |
| ...(handoff ? { handoff } : {}), |
| }; |
| } |
|
|
| |
| export function validateTemplateForm(f: TemplateForm): string | null { |
| if (!f.title.trim()) return 'Give the template a title.'; |
| if (!f.artifactPath.startsWith('/.interviews/')) return 'The artifact path must be under /.interviews/.'; |
| if (!f.artifactPath.endsWith('.md')) return 'The artifact path must end in .md.'; |
| if (f.artifactPath.includes('..')) return 'The artifact path cannot contain "..".'; |
| if (f.items.length === 0) return 'Add at least one item.'; |
| for (const i of f.items) { |
| if (!i.question.trim()) return 'Every item needs a question.'; |
| if (!i.criteria.trim()) return 'Every item needs a "done when" criteria.'; |
| } |
| return null; |
| } |
|
|