Name outputs from the input, engine, and LoRA keys instead of aigen_0001. Image-edit presets now store prompts, and aspect fill pads stills without stretching.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+54
-4
@@ -8,6 +8,8 @@ import type { H3Event } from 'h3'
|
||||
import { extractFirstFrame, extractFrameAt, extractLastFrame, probeDuration, remuxFaststart } from '~/server/utils/ffmpeg'
|
||||
import { normalizePermanenceRefs, type PermanenceRef } from '~/utils/globalLocks'
|
||||
import { normalizeStillSettings, type StillGenerationSettings } from '~/utils/libraryGeneration'
|
||||
import { buildOutputBaseName, nextUniqueName, normalizeLoraAliases, sanitizeLoraAlias } from '~/utils/outputNames'
|
||||
import { loraIdentityKey, type LoraStackItem } from '~/utils/loras'
|
||||
|
||||
const scryptAsync = promisify(scrypt)
|
||||
|
||||
@@ -128,6 +130,7 @@ interface Catalog {
|
||||
clips: LibraryClip[]
|
||||
stills: LibraryStill[]
|
||||
drafts: RetryDraft[]
|
||||
loraAliases: Record<string, string>
|
||||
}
|
||||
|
||||
const writeChains = new Map<string, Promise<unknown>>()
|
||||
@@ -166,7 +169,8 @@ function emptyCatalog(): Catalog {
|
||||
}],
|
||||
clips: [],
|
||||
stills: [],
|
||||
drafts: []
|
||||
drafts: [],
|
||||
loraAliases: {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +229,8 @@ function normalizeCatalog(parsed: Partial<Catalog> & { passwordHash?: string | n
|
||||
folders,
|
||||
clips: Array.isArray(parsed.clips) ? parsed.clips : [],
|
||||
stills: Array.isArray(parsed.stills) ? parsed.stills.map(normalizeStill) : [],
|
||||
drafts: Array.isArray(parsed.drafts) ? parsed.drafts : []
|
||||
drafts: Array.isArray(parsed.drafts) ? parsed.drafts : [],
|
||||
loraAliases: normalizeLoraAliases(parsed.loraAliases)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +364,51 @@ export function stillChainName(base: string, index: number) {
|
||||
|
||||
export function safeDownloadName(name: string) {
|
||||
const cleaned = name.replace(/[<>:"/\\|?*'`\u0000-\u001f]/g, '-').replace(/\s+/g, ' ').trim()
|
||||
return cleaned.slice(0, 80) || 'aigen'
|
||||
return cleaned.slice(0, 80) || 'output'
|
||||
}
|
||||
|
||||
function existingOutputNames(catalog: Catalog, folderId: string) {
|
||||
const stills = catalog.stills
|
||||
.filter(item => item.folderId === folderId)
|
||||
.map(item => String(item.name || '').trim())
|
||||
.filter(Boolean)
|
||||
const clips = catalog.clips
|
||||
.filter(item => item.folderId === folderId)
|
||||
.map(item => String(item.name || '').trim())
|
||||
.filter(Boolean)
|
||||
return [...stills, ...clips]
|
||||
}
|
||||
|
||||
export function getLoraAliases(owner: string) {
|
||||
return { ...(readCatalog(owner).loraAliases || {}) }
|
||||
}
|
||||
|
||||
export async function setLoraAlias(owner: string, identity: string, alias: string) {
|
||||
const key = loraIdentityKey(identity) || String(identity || '').trim().toLowerCase()
|
||||
if (!key) throw createError({ statusCode: 400, statusMessage: 'A LoRA file is required' })
|
||||
const cleaned = sanitizeLoraAlias(alias)
|
||||
return mutate(owner, (catalog) => {
|
||||
if (!catalog.loraAliases) catalog.loraAliases = {}
|
||||
if (!cleaned) delete catalog.loraAliases[key]
|
||||
else catalog.loraAliases[key] = cleaned
|
||||
return { ...catalog.loraAliases }
|
||||
})
|
||||
}
|
||||
|
||||
export function allocateOutputName(owner: string, folderId: string, requested: string, opts: {
|
||||
inputFilename?: string
|
||||
engine: string
|
||||
loraStack?: LoraStackItem[] | unknown
|
||||
}) {
|
||||
const catalog = readCatalog(owner)
|
||||
const base = buildOutputBaseName({
|
||||
requested,
|
||||
inputFilename: opts.inputFilename,
|
||||
engine: opts.engine,
|
||||
loraStack: opts.loraStack,
|
||||
aliases: catalog.loraAliases || {}
|
||||
})
|
||||
return nextUniqueName(existingOutputNames(catalog, folderId), base)
|
||||
}
|
||||
|
||||
export function passwordVersion(hash: string | null) {
|
||||
@@ -425,7 +474,8 @@ export function publicLibrary(event: H3Event) {
|
||||
stills: catalog.stills
|
||||
.filter(still => unlockedIds.has(still.folderId) && !isPipelineStill(catalog, still))
|
||||
.map(still => ({ ...still, role: stillRole(still) })),
|
||||
drafts: catalog.drafts
|
||||
drafts: catalog.drafts,
|
||||
loraAliases: catalog.loraAliases || {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user