Files
aigen/server/api/studio-queue.get.ts
T

77 lines
3.3 KiB
TypeScript

import { listShotQueues, summarizeQueue } from '~/server/utils/shotQueue'
import { kickStudioQueue, listStudioJobs, summarizeStudioJob } from '~/server/utils/studioQueue'
export default defineEventHandler((event) => {
const { owner } = assertLibraryOwner(event)
const full = String(getQuery(event).full || '') === '1'
const active = listStudioJobs(owner)
.filter(job => !job.dismissed)
.filter(job => (
job.status === 'waiting'
|| job.status === 'running'
|| job.status === 'held'
|| (job.status === 'error' && Date.now() - job.updatedAt < 60 * 60 * 1000)
|| (job.kind === 'caption' && job.status === 'complete' && Date.now() - job.updatedAt < 60 * 60 * 1000)
|| (job.kind === 'caption' && job.status === 'cancelled' && Date.now() - job.updatedAt < 60 * 60 * 1000)
))
const claimed = new Set(active.map(job => job.shotQueueId).filter(Boolean) as string[])
const queues = listShotQueues(owner)
const byId = new Map(queues.map(queue => [queue.id, queue]))
const jobs = active.map((job) => {
const shots = job.shotQueueId ? byId.get(job.shotQueueId) || null : null
const kind = job.kind === 'edit' ? 'edit' : job.kind === 'music' ? 'music' : job.kind === 'caption' ? 'caption' : 'video'
const shotSummary = shots ? summarizeQueue(shots) : null
const plannedShots = shotSummary
? undefined
: kind === 'music'
? undefined
: kind === 'edit'
? (job.payload.passes?.length
? [
{ prompt: job.payload.prompt, duration: 0 },
...job.payload.passes.map(item => ({ prompt: item.prompt, duration: 0 }))
]
: undefined)
: [
{ prompt: job.payload.prompt, duration: job.payload.duration, loraName: job.payload.shotLoras?.[0] || job.payload.loraName, loraStack: job.payload.shotLoraStacks?.[0] || job.payload.loraStack },
...(job.payload.extensions || []).map((item, index) => ({
prompt: item.prompt,
duration: item.duration,
loraName: item.loraName || job.payload.shotLoras?.[index + 1],
loraStack: item.loraStack || job.payload.shotLoraStacks?.[index + 1]
}))
]
return {
...summarizeStudioJob(job),
source: 'studio' as const,
...(full ? {
shots: shotSummary,
plannedShots: plannedShots && plannedShots.length > 1 ? plannedShots : undefined
} : {}),
completedCount: shotSummary?.completedCount || 0,
pendingCount: shotSummary?.pendingCount ?? job.shotCount
}
})
const orphans = full
? queues
.filter(queue => !claimed.has(queue.id) && queue.status !== 'complete')
.map(summarizeQueue)
: []
const waitingCount = jobs.filter(job => job.status === 'waiting').length
// Nudge the dispatcher whenever the UI polls a stalled waiting queue.
if (waitingCount > 0 && !jobs.some(job => job.status === 'running')) {
void kickStudioQueue()
}
return {
jobs,
orphans,
waitingCount,
paused: jobs.some(job => job.pausedByUser === true)
|| orphans.some(queue => queue.stopAfterCurrent === true && queue.status !== 'running'),
willPause: jobs.some(job => (
job.pauseAfterCurrent === true
|| (job.status === 'running' && Boolean(job.shotQueueId && byId.get(job.shotQueueId)?.stopAfterCurrent))
))
}
})