import { loadAdvisorDraft, loadPersonaDraft, saveAdvisorDraft, savePersonaDraft, syncAdvisorToServerIfAuthed, syncPersonaToServerIfAuthed, } from './drafts' import { syncAdvisorDraftToCreations, syncPersonaDraftToCreations } from './draftCreationsSync' import { ADVISOR_DRAFT_CHAT_STRING_KEYS } from './advisorPanelFormModel' import { PERSONA_FORM_KEYS } from './personaFormModel' const ADVISOR_DRAFT_KEY = 'advisor_draft_v1' const PERSONA_DRAFT_KEY = 'persona_draft_v1' /** Merge model `draft_update` into local persona form draft; preserves `_wizardStep` and other extras. */ export function mergePersonaDraftFromChat(draftUpdate: Record | null | undefined) { if (!draftUpdate || typeof draftUpdate !== 'object') return const cur = loadPersonaDraft() const next: Record = { ...cur } for (const k of PERSONA_FORM_KEYS) { const raw = draftUpdate[k] let t = '' if (typeof raw === 'string') t = raw.trim() else if ( typeof raw === 'number' && Number.isFinite(raw) && k === 'creativityLevel' ) { t = String(Math.min(10, Math.max(0, Math.round(raw)))) } else continue if (t !== '') next[k] = t } savePersonaDraft(next) syncPersonaDraftToCreations() void syncPersonaToServerIfAuthed() } function normalizeAdvisorRows(raw: unknown): { name: string; role: string }[] { if (!Array.isArray(raw)) return [] return raw .map((x) => { const o = x as Record return { name: String(o?.name ?? '').trim(), role: String(o?.role ?? '').trim(), } }) .filter((r) => r.name || r.role) } /** Merge model `draft_update` into local advisor form draft. */ export function mergeAdvisorDraftFromChat(draftUpdate: Record | null | undefined) { if (!draftUpdate || typeof draftUpdate !== 'object') return const cur = loadAdvisorDraft() const next: Record = { ...cur } for (const k of ADVISOR_DRAFT_CHAT_STRING_KEYS) { const raw = draftUpdate[k] if (typeof raw === 'string' && raw.trim()) next[k] = raw.trim() } const rows = normalizeAdvisorRows(draftUpdate.advisors) if (rows.length) next.advisors = rows saveAdvisorDraft(next) syncAdvisorDraftToCreations() void syncAdvisorToServerIfAuthed() } /** Strip internal wizard keys before sending draft to the API. */ export function advisorDraftSnapshotForChat(): Record { const d = loadAdvisorDraft() const out: Record = {} for (const [k, v] of Object.entries(d)) { if (k.startsWith('_')) continue out[k] = v } return out } export function personaDraftSnapshotForChat(): Record { const d = loadPersonaDraft() const out: Record = {} for (const [k, v] of Object.entries(d)) { if (k.startsWith('_')) continue out[k] = v } return out } function isFilled(v: unknown): boolean { if (typeof v === 'string') return v.trim() !== '' if (Array.isArray(v)) return v.length > 0 return false } /** Progress (0-100) derived from how many canonical fields the saved draft already has. */ export function computeAdvisorDraftProgress(): number { const d = loadAdvisorDraft() const total = ADVISOR_DRAFT_CHAT_STRING_KEYS.length + 1 // + advisors let filled = 0 for (const k of ADVISOR_DRAFT_CHAT_STRING_KEYS) if (isFilled(d[k])) filled += 1 if (isFilled(d.advisors)) filled += 1 return Math.round((filled / total) * 100) } export function computePersonaDraftProgress(): number { const d = loadPersonaDraft() const total = PERSONA_FORM_KEYS.length let filled = 0 for (const k of PERSONA_FORM_KEYS) if (isFilled(d[k])) filled += 1 return Math.round((filled / total) * 100) } export function advisorDraftName(): string { const d = loadAdvisorDraft() const name = d.panelName return typeof name === 'string' ? name.trim() : '' } export function personaDraftName(): string { const d = loadPersonaDraft() const name = d.advisorPersonaName return typeof name === 'string' ? name.trim() : '' } /** Reset the advisor draft so a brand-new chat does not inherit another panel's data/_editingId. */ export function resetAdvisorDraftForNewChat() { try { localStorage.removeItem(ADVISOR_DRAFT_KEY) } catch { /* */ } } export function resetPersonaDraftForNewChat() { try { localStorage.removeItem(PERSONA_DRAFT_KEY) } catch { /* */ } }