Extend Prompt Builder with sequence characters, outfits, and scene toggles.
Characters live on the sequence with per-scene on/off and outfit picks; Copy scene exports only the active tab; legacy saves still open.
This commit is contained in:
@@ -4,11 +4,13 @@ export default defineEventHandler(async (event) => {
|
||||
const { owner } = assertLibraryOwner(event)
|
||||
const body = await readBody<{
|
||||
name?: string
|
||||
characters?: unknown
|
||||
scenes?: unknown
|
||||
overwrite?: boolean
|
||||
}>(event).catch(() => ({}))
|
||||
const sequence = await savePromptSequence(owner, {
|
||||
name: body?.name || '',
|
||||
characters: body?.characters,
|
||||
scenes: body?.scenes,
|
||||
overwrite: body?.overwrite === true
|
||||
})
|
||||
|
||||
@@ -3,9 +3,10 @@ import { listPromptSequences, updatePromptSequence } from '~/server/utils/prompt
|
||||
export default defineEventHandler(async (event) => {
|
||||
const { owner } = assertLibraryOwner(event)
|
||||
const id = String(getRouterParam(event, 'id') || '')
|
||||
const body = await readBody<{ name?: string; scenes?: unknown }>(event).catch(() => ({}))
|
||||
const body = await readBody<{ name?: string; characters?: unknown; scenes?: unknown }>(event).catch(() => ({}))
|
||||
const sequence = await updatePromptSequence(owner, id, {
|
||||
name: body?.name,
|
||||
characters: body?.characters,
|
||||
scenes: body?.scenes
|
||||
})
|
||||
return {
|
||||
|
||||
@@ -4,9 +4,12 @@ import { ownerRoot } from '~/server/utils/library'
|
||||
import {
|
||||
normalizePromptSequence,
|
||||
normalizePromptSequenceName,
|
||||
normalizeCharacter,
|
||||
normalizeScene,
|
||||
emptyCharacter,
|
||||
emptyScene,
|
||||
type PromptSequence,
|
||||
type PromptSequenceCharacter,
|
||||
type PromptSequenceScene
|
||||
} from '~/utils/promptSequences'
|
||||
|
||||
@@ -54,9 +57,14 @@ function mutate<T>(owner: string, fn: (sequences: PromptSequence[]) => T): Promi
|
||||
return run
|
||||
}
|
||||
|
||||
function normalizeScenesInput(raw: unknown): PromptSequenceScene[] {
|
||||
if (!Array.isArray(raw) || !raw.length) return [emptyScene(1)]
|
||||
return raw.map((scene, index) => normalizeScene(scene, index))
|
||||
function normalizeCharactersInput(raw: unknown): PromptSequenceCharacter[] {
|
||||
if (!Array.isArray(raw) || !raw.length) return [emptyCharacter()]
|
||||
return raw.map(normalizeCharacter)
|
||||
}
|
||||
|
||||
function normalizeScenesInput(raw: unknown, characters: PromptSequenceCharacter[]): PromptSequenceScene[] {
|
||||
if (!Array.isArray(raw) || !raw.length) return [emptyScene(1, characters)]
|
||||
return raw.map((scene, index) => normalizeScene(scene, index, characters))
|
||||
}
|
||||
|
||||
export function listPromptSequences(owner: string) {
|
||||
@@ -72,12 +80,14 @@ export function getPromptSequence(owner: string, id: string) {
|
||||
|
||||
export async function savePromptSequence(owner: string, input: {
|
||||
name: string
|
||||
characters?: unknown
|
||||
scenes?: unknown
|
||||
overwrite?: boolean
|
||||
}) {
|
||||
const name = normalizePromptSequenceName(input.name)
|
||||
if (!name) throw createError({ statusCode: 400, statusMessage: 'A sequence name is required' })
|
||||
const scenes = normalizeScenesInput(input.scenes)
|
||||
const characters = normalizeCharactersInput(input.characters)
|
||||
const scenes = normalizeScenesInput(input.scenes, characters)
|
||||
const now = Date.now()
|
||||
return mutate(owner, (sequences) => {
|
||||
const existing = sequences.find(item => item.name.toLowerCase() === name.toLowerCase())
|
||||
@@ -85,6 +95,7 @@ export async function savePromptSequence(owner: string, input: {
|
||||
throw createError({ statusCode: 409, statusMessage: `Overwrite sequence “${existing.name}”?` })
|
||||
}
|
||||
if (existing) {
|
||||
existing.characters = characters
|
||||
existing.scenes = scenes
|
||||
existing.updatedAt = now
|
||||
return existing
|
||||
@@ -92,6 +103,7 @@ export async function savePromptSequence(owner: string, input: {
|
||||
const created: PromptSequence = {
|
||||
id: crypto.randomUUID(),
|
||||
name,
|
||||
characters,
|
||||
scenes,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
@@ -103,6 +115,7 @@ export async function savePromptSequence(owner: string, input: {
|
||||
|
||||
export async function updatePromptSequence(owner: string, id: string, input: {
|
||||
name?: string
|
||||
characters?: unknown
|
||||
scenes?: unknown
|
||||
}) {
|
||||
const wanted = String(id || '').trim()
|
||||
@@ -117,8 +130,15 @@ export async function updatePromptSequence(owner: string, id: string, input: {
|
||||
if (clash) throw createError({ statusCode: 409, statusMessage: `A sequence named “${clash.name}” already exists` })
|
||||
existing.name = name
|
||||
}
|
||||
if (input.scenes !== undefined) {
|
||||
existing.scenes = normalizeScenesInput(input.scenes)
|
||||
if (input.characters !== undefined || input.scenes !== undefined) {
|
||||
const characters = input.characters !== undefined
|
||||
? normalizeCharactersInput(input.characters)
|
||||
: existing.characters
|
||||
const scenes = input.scenes !== undefined
|
||||
? normalizeScenesInput(input.scenes, characters)
|
||||
: existing.scenes.map((scene, index) => normalizeScene(scene, index, characters))
|
||||
existing.characters = characters
|
||||
existing.scenes = scenes
|
||||
}
|
||||
existing.updatedAt = Date.now()
|
||||
return existing
|
||||
|
||||
Reference in New Issue
Block a user