export type PromptParts = { pre: string prompt: string post: string } export function sanitizePromptPart(raw: unknown) { return String(raw || '').replace(/\r\n/g, '\n').replace(/\r/g, '') } export function composePromptParts(pre: string, prompt: string, post: string) { return [pre, prompt, post] .map(part => sanitizePromptPart(part).trim()) .filter(Boolean) .join('\n\n') } export function applyPromptParts(parts: PromptParts, middle: string) { return composePromptParts(parts.pre, middle, parts.post) } function peelPromptWrappers(mid: string, pre: string, post: string) { let next = sanitizePromptPart(mid) if (pre && next.startsWith(pre)) next = next.slice(pre.length).replace(/^\n+/, '') if (post && next.endsWith(post)) next = next.slice(0, Math.max(0, next.length - post.length)).replace(/\n+$/, '') return next.trim() } export function restorePromptParts(saved: string, stored?: Partial | null): PromptParts { const pre = sanitizePromptPart(stored?.pre ?? '').trim() const post = sanitizePromptPart(stored?.post ?? '').trim() return { pre, prompt: peelPromptWrappers(stored?.prompt ?? saved, pre, post), post } } export function formatPromptParts( stored?: { prompt?: string; promptPre?: string; promptPost?: string } | null, midOverride?: string ) { const pre = sanitizePromptPart(stored?.promptPre || '').trim() const post = sanitizePromptPart(stored?.promptPost || '').trim() const prompt = peelPromptWrappers(midOverride ?? stored?.prompt ?? '', pre, post) const blocks: string[] = [] if (pre) blocks.push(`Pre-text\n${pre}`) if (prompt) blocks.push(pre || post ? `Prompt\n${prompt}` : prompt) if (post) blocks.push(`Post-text\n${post}`) return blocks.join('\n\n') }