builder / lib /interview /template-form.ts
Leon4gr45's picture
Upload folder using huggingface_hub (part 2)
391c43e verified
Raw
History Blame Contribute Delete
2.75 kB
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;
}
/** Slug used for template ids and item ids. Mirrors SkillsService.slugify. */
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 } : {}),
};
}
/** Returns an error message, or null if valid. */
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;
}