Add LoRA stacks with per-item strengths and named video/image generation presets so setups survive reload without mixing Klein onto MiniMax. Keep LTX Pink Cherry and xAIGen LoRAs on xAIGen, and run Recommend on Beast.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -21,6 +21,9 @@ import {
|
||||
updateShotQueue
|
||||
} from '~/server/utils/shotQueue'
|
||||
import { composeShotPrompt, allowIdentityRefs, type PermanenceRef } from '~/utils/globalLocks'
|
||||
import { persistLoraFields } from '~/server/utils/loras'
|
||||
import { readLoraStack, resolveLoraStack } from '~/utils/loras'
|
||||
import type { LoraStackItem } from '~/utils/loras'
|
||||
|
||||
export type ChainImage = { filename: string; data: Buffer; type?: string }
|
||||
|
||||
@@ -38,7 +41,7 @@ type VideoChainParams = {
|
||||
fps: number
|
||||
samplerName: string
|
||||
scheduler: string
|
||||
extensions: { prompt: string; duration: number }[]
|
||||
extensions: { prompt: string; duration: number; loraName?: string; loraStack?: LoraStackItem[]; permanenceRefs?: PermanenceRef[] }[]
|
||||
workflow: VideoWorkflowId
|
||||
duration: number
|
||||
useIdentityRefs: boolean
|
||||
@@ -46,6 +49,10 @@ type VideoChainParams = {
|
||||
globalLocks?: string
|
||||
permanenceRefs?: PermanenceRef[]
|
||||
shotPermanenceRefs?: PermanenceRef[][]
|
||||
loraName?: string
|
||||
loraStack?: LoraStackItem[]
|
||||
shotLoras?: string[]
|
||||
shotLoraStacks?: LoraStackItem[][]
|
||||
}
|
||||
|
||||
function sleep(ms: number) {
|
||||
@@ -119,7 +126,10 @@ function paramsFromJob(job: Job): VideoChainParams {
|
||||
referenceImages,
|
||||
globalLocks: library.globalLocks,
|
||||
permanenceRefs: library.permanenceRefs,
|
||||
shotPermanenceRefs: library.shotPermanenceRefs
|
||||
shotPermanenceRefs: library.shotPermanenceRefs,
|
||||
...persistLoraFields(readLoraStack(library)),
|
||||
shotLoras: library.shotLoras,
|
||||
shotLoraStacks: library.shotLoraStacks
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +147,7 @@ export async function queueMiniMax(
|
||||
job.status = 'uploading'
|
||||
const chainIndex = job.library?.chainIndex || 0
|
||||
const graphId = chainIndex > 0 ? workflowForExtension(params.workflow) : params.workflow
|
||||
if (job.library) Object.assign(job.library, persistLoraFields(params.loraStack || params.loraName || job.library.loraStack || job.library.loraName))
|
||||
const engineName = isLtxWorkflow(graphId) ? 'LTX-2.3' : 'MiniMax H3'
|
||||
const hasImage = Boolean(params.image?.data?.length)
|
||||
const uploading = !hasImage
|
||||
@@ -197,7 +208,8 @@ export async function queueMiniMax(
|
||||
workflow: graphId,
|
||||
duration: params.duration,
|
||||
useIdentityRefs: params.useIdentityRefs,
|
||||
referenceImageNames: params.useIdentityRefs ? referenceNames : []
|
||||
referenceImageNames: params.useIdentityRefs ? referenceNames : [],
|
||||
...persistLoraFields(params.loraStack || params.loraName)
|
||||
})
|
||||
|
||||
const queued = await queuePrompt(graph, job.clientId)
|
||||
@@ -305,6 +317,10 @@ export async function continueQueuedExtensions(
|
||||
prompt: live.prompt || extensions[i].prompt,
|
||||
duration: live.duration || extensions[i].duration
|
||||
}
|
||||
const shotStack = resolveLoraStack(
|
||||
readLoraStack(liveQueue).length ? readLoraStack(liveQueue) : (params.loraStack || params.loraName),
|
||||
live.loraStack || live.loraName || extensions[i]?.loraStack || extensions[i]?.loraName
|
||||
)
|
||||
if (!ext.prompt.trim()) {
|
||||
throw new Error(`Shot ${i + 2} needs a prompt`)
|
||||
}
|
||||
@@ -328,6 +344,7 @@ export async function continueQueuedExtensions(
|
||||
job.library.extendPart1Path = undefined
|
||||
job.library.thumb = undefined
|
||||
job.library.duration = ext.duration
|
||||
Object.assign(job.library, persistLoraFields(shotStack))
|
||||
if (liveQueue) {
|
||||
await updateShotQueue(job.library.ownerKey, liveQueue.id, (queue) => {
|
||||
const segment = queue.segments.find(item => item.index === i + 1)
|
||||
@@ -393,7 +410,8 @@ export async function continueQueuedExtensions(
|
||||
workflow: workflowForExtension(params.workflow),
|
||||
duration: ext.duration,
|
||||
useIdentityRefs: identity,
|
||||
referenceImages: identity ? params.referenceImages : []
|
||||
referenceImages: identity ? params.referenceImages : [],
|
||||
...persistLoraFields(shotStack)
|
||||
})
|
||||
|
||||
shotsLeft -= 1
|
||||
@@ -548,7 +566,8 @@ export async function startQueueBurst(owner: string, queueId: string, count: num
|
||||
queueBudget: n,
|
||||
globalLocks: queue.globalLocks,
|
||||
permanenceRefs: queue.permanenceRefs,
|
||||
shotPermanenceRefs: queue.segments.map(segment => segment.permanenceRefs || [])
|
||||
shotPermanenceRefs: queue.segments.map(segment => segment.permanenceRefs || []),
|
||||
...persistLoraFields(readLoraStack(queue))
|
||||
}
|
||||
setQueueJob(queue.id, job.id)
|
||||
await updateShotQueue(owner, queue.id, (next) => {
|
||||
|
||||
Reference in New Issue
Block a user