Add Prompt Builder sequence section order.
Copied scene text and the scene editor follow a persisted sectionOrder, with legacy saves keeping the default style/settings/set/characters/prompt order. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -50,9 +50,18 @@ export type PromptSequenceScene = {
|
||||
prompt: string
|
||||
}
|
||||
|
||||
/** Scene prompt sections. Default copy order. */
|
||||
export const PROMPT_SEQUENCE_SECTION_KEYS = ['style', 'settings', 'set', 'characters', 'prompt'] as const
|
||||
export type PromptSequenceSectionKey = (typeof PROMPT_SEQUENCE_SECTION_KEYS)[number]
|
||||
export const DEFAULT_PROMPT_SEQUENCE_SECTION_ORDER: PromptSequenceSectionKey[] = [
|
||||
...PROMPT_SEQUENCE_SECTION_KEYS
|
||||
]
|
||||
|
||||
export type PromptSequence = {
|
||||
id: string
|
||||
name: string
|
||||
/** Order of scene sections when assembling / in the editor. */
|
||||
sectionOrder: PromptSequenceSectionKey[]
|
||||
characters: PromptSequenceCharacter[]
|
||||
sets: PromptSequenceSet[]
|
||||
scenes: PromptSequenceScene[]
|
||||
@@ -60,6 +69,26 @@ export type PromptSequence = {
|
||||
updatedAt: number
|
||||
}
|
||||
|
||||
/** Valid unique keys in given order; missing keys append in default order. */
|
||||
export function normalizeSectionOrder(raw: unknown): PromptSequenceSectionKey[] {
|
||||
const allowed = new Set<string>(PROMPT_SEQUENCE_SECTION_KEYS)
|
||||
const seen = new Set<PromptSequenceSectionKey>()
|
||||
const ordered: PromptSequenceSectionKey[] = []
|
||||
if (Array.isArray(raw)) {
|
||||
for (const item of raw) {
|
||||
const key = String(item || '').trim()
|
||||
if (!allowed.has(key) || seen.has(key as PromptSequenceSectionKey)) continue
|
||||
const typed = key as PromptSequenceSectionKey
|
||||
seen.add(typed)
|
||||
ordered.push(typed)
|
||||
}
|
||||
}
|
||||
for (const key of DEFAULT_PROMPT_SEQUENCE_SECTION_ORDER) {
|
||||
if (!seen.has(key)) ordered.push(key)
|
||||
}
|
||||
return ordered
|
||||
}
|
||||
|
||||
export const PROMPT_SEQUENCE_NAME_MAX = 80
|
||||
export const PROMPT_SEQUENCE_FIELD_MAX = 50_000
|
||||
export const PROMPT_SEQUENCE_TITLE_MAX = 60
|
||||
@@ -206,7 +235,8 @@ export function assembleSceneText(
|
||||
characters?: Array<{ name?: string; description?: string }>
|
||||
},
|
||||
sequenceCharacters?: PromptSequenceCharacter[],
|
||||
sequenceSets?: PromptSequenceSet[]
|
||||
sequenceSets?: PromptSequenceSet[],
|
||||
sectionOrder?: PromptSequenceSectionKey[] | unknown
|
||||
) {
|
||||
const setBlock = sequenceSets?.length
|
||||
? assembleSetBlock(scene, sequenceSets)
|
||||
@@ -217,13 +247,15 @@ export function assembleSceneText(
|
||||
.map(character => formatCharacterLine(character))
|
||||
.filter(Boolean)
|
||||
.join('\n')
|
||||
const parts = [
|
||||
String(scene.style || '').trim(),
|
||||
String(scene.settings || '').trim(),
|
||||
setBlock,
|
||||
characterBlock,
|
||||
String(scene.prompt || '').trim()
|
||||
].filter(Boolean)
|
||||
const blocks: Record<PromptSequenceSectionKey, string> = {
|
||||
style: String(scene.style || '').trim(),
|
||||
settings: String(scene.settings || '').trim(),
|
||||
set: setBlock,
|
||||
characters: characterBlock,
|
||||
prompt: String(scene.prompt || '').trim()
|
||||
}
|
||||
const order = normalizeSectionOrder(sectionOrder)
|
||||
const parts = order.map(key => blocks[key]).filter(Boolean)
|
||||
return parts.join('\n\n')
|
||||
}
|
||||
|
||||
@@ -233,6 +265,7 @@ export function assembleSceneText(
|
||||
* Sequence name is never included.
|
||||
*/
|
||||
export function assembleSequenceText(sequence: {
|
||||
sectionOrder?: PromptSequenceSectionKey[] | unknown
|
||||
characters?: PromptSequenceCharacter[]
|
||||
sets?: PromptSequenceSet[]
|
||||
scenes?: Array<{
|
||||
@@ -246,11 +279,13 @@ export function assembleSequenceText(sequence: {
|
||||
}) {
|
||||
const characters = sequence.characters || []
|
||||
const sets = sequence.sets || []
|
||||
const sectionOrder = normalizeSectionOrder(sequence.sectionOrder)
|
||||
return (sequence.scenes || [])
|
||||
.map(scene => assembleSceneText(
|
||||
scene,
|
||||
characters.length ? characters : undefined,
|
||||
sets.length ? sets : undefined
|
||||
sets.length ? sets : undefined,
|
||||
sectionOrder
|
||||
))
|
||||
.filter(Boolean)
|
||||
.join('\n\n\n')
|
||||
@@ -478,6 +513,7 @@ export function normalizePromptSequence(raw: unknown): PromptSequence | null {
|
||||
return {
|
||||
id: String(rec.id || '').trim() || newId(),
|
||||
name,
|
||||
sectionOrder: normalizeSectionOrder(rec.sectionOrder),
|
||||
characters,
|
||||
sets,
|
||||
scenes,
|
||||
|
||||
Reference in New Issue
Block a user