File size: 3,535 Bytes
b435029 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | import type { PromptLocale } from '../../types'
export interface ProblemFramingStep {
title: string
content: string
}
export interface ProblemFramingPlan {
mode: 'clarify' | 'invent'
headline: string
summary: string
steps: ProblemFramingStep[]
visualMotif: string
designerHint: string
}
function stripCodeFence(text: string): string {
return text
.replace(/^```json\s*/i, '')
.replace(/^```\s*/i, '')
.replace(/\s*```$/, '')
.trim()
}
export function extractProblemFramingJson(text: string): string {
const cleaned = stripCodeFence(text)
if (/^\s*<!DOCTYPE\s+html/i.test(cleaned) || /^\s*<html/i.test(cleaned)) {
throw new Error('Problem framing response was HTML, not JSON')
}
const start = cleaned.indexOf('{')
const end = cleaned.lastIndexOf('}')
if (start === -1 || end === -1 || end <= start) {
throw new Error('Problem framing response did not contain a JSON object')
}
return cleaned.slice(start, end + 1)
}
function sanitizeString(value: unknown, fallback: string): string {
if (typeof value !== 'string') {
return fallback
}
const normalized = value.trim().replace(/\s+/g, ' ')
return normalized || fallback
}
export function normalizeProblemFramingPlan(raw: unknown, locale: PromptLocale): ProblemFramingPlan {
if (!raw || typeof raw !== 'object') {
throw new Error('Problem framing response was not an object')
}
const input = raw as {
mode?: unknown
headline?: unknown
summary?: unknown
steps?: unknown
visualMotif?: unknown
visual_motif?: unknown
designerHint?: unknown
designer_hint?: unknown
}
const fallbackStepTitle = locale === 'en-US' ? 'Step' : '步骤'
const fallbackStepContent = locale === 'en-US'
? 'Continue clarifying the visual direction and storytelling order for this part.'
: '继续细化这一段的可视化表达和叙事顺序。'
const fallbackHeadline = locale === 'en-US' ? 'A fresh visualization plan' : '新的可视化方案'
const fallbackSummary = locale === 'en-US'
? 'The expression path has been organized more clearly.'
: '整理出一个更清晰的表达路径。'
const fallbackMotif = locale === 'en-US' ? 'Cat paws are sorting the steps across the card.' : '猫爪在卡片上整理出步骤。'
const fallbackHint = locale === 'en-US'
? 'The next designer stage should expand these three steps into concrete animation design.'
: '下一阶段继续把三步扩成具体动画设计。'
const steps = Array.isArray(input.steps) ? input.steps : []
const normalizedSteps = steps
.slice(0, 5)
.map((step, index) => {
const item = step && typeof step === 'object' ? step as { title?: unknown; content?: unknown } : {}
return {
title: sanitizeString(item.title, `${fallbackStepTitle} ${index + 1}`),
content: sanitizeString(item.content, ''),
}
})
.filter((step) => step.content)
while (normalizedSteps.length < 3) {
normalizedSteps.push({
title: `${fallbackStepTitle} ${normalizedSteps.length + 1}`,
content: fallbackStepContent,
})
}
return {
mode: input.mode === 'clarify' ? 'clarify' : 'invent',
headline: sanitizeString(input.headline, fallbackHeadline),
summary: sanitizeString(input.summary, fallbackSummary),
steps: normalizedSteps,
visualMotif: sanitizeString(input.visualMotif ?? input.visual_motif, fallbackMotif),
designerHint: sanitizeString(input.designerHint ?? input.designer_hint, fallbackHint),
}
}
|