AdvisoryBuilderWorkshop / frontend /src /lib /chatDraftMerge.ts
NeonClary's picture
Deploy tutorial feature and recent fixes
d8808e7 verified
Raw
History Blame Contribute Delete
4.59 kB
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<string, unknown> | null | undefined) {
if (!draftUpdate || typeof draftUpdate !== 'object') return
const cur = loadPersonaDraft()
const next: Record<string, unknown> = { ...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<string, unknown>
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<string, unknown> | null | undefined) {
if (!draftUpdate || typeof draftUpdate !== 'object') return
const cur = loadAdvisorDraft()
const next: Record<string, unknown> = { ...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<string, unknown> {
const d = loadAdvisorDraft()
const out: Record<string, unknown> = {}
for (const [k, v] of Object.entries(d)) {
if (k.startsWith('_')) continue
out[k] = v
}
return out
}
export function personaDraftSnapshotForChat(): Record<string, unknown> {
const d = loadPersonaDraft()
const out: Record<string, unknown> = {}
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 {
/* */
}
}