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) } export function restorePromptParts(saved: string, stored?: Partial | null, current?: Partial | null): PromptParts { const pre = sanitizePromptPart(stored?.pre ?? '').trim() const post = sanitizePromptPart(stored?.post ?? '').trim() if (pre || post) { return { pre, prompt: sanitizePromptPart(stored?.prompt ?? saved).trim() || sanitizePromptPart(saved).trim(), post } } let mid = sanitizePromptPart(stored?.prompt ?? saved) const curPre = sanitizePromptPart(current?.pre || '').trim() const curPost = sanitizePromptPart(current?.post || '').trim() if (curPre && mid.startsWith(curPre)) mid = mid.slice(curPre.length).replace(/^\n+/, '') if (curPost && mid.endsWith(curPost)) mid = mid.slice(0, Math.max(0, mid.length - curPost.length)).replace(/\n+$/, '') return { pre: current?.pre || '', prompt: mid.trim(), post: current?.post || '' } }