File size: 2,893 Bytes
d47b053 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | import { v4 as uuidv4 } from 'uuid'
import type { StudioToolDefinition, StudioToolResult } from '../domain/types'
import type { StudioRuntimeBackedToolContext } from '../runtime/tool-runtime-context'
import type { CustomApiConfig, OutputMode, VideoQuality } from '../../types'
import { videoQueue } from '../../config/bull'
import { storeJobStage } from '../../services/job-store'
import { createWorkAndTask } from '../works/work-lifecycle'
import { resolveJobTimeoutMs } from '../../utils/job-timeout'
interface RenderToolInput {
concept: string
code: string
outputMode?: OutputMode
quality?: VideoQuality
customApiConfig?: CustomApiConfig
}
export function createStudioRenderTool(): StudioToolDefinition<RenderToolInput> {
return {
name: 'render',
description: 'Create a Manim render task backed by the existing queue.',
category: 'render',
permission: 'render',
allowedAgents: ['builder'],
allowedStudioKinds: ['manim'],
requiresTask: true,
execute: async (input, context) => executeRenderTool(input, context as StudioRuntimeBackedToolContext)
}
}
async function executeRenderTool(
input: RenderToolInput,
context: StudioRuntimeBackedToolContext
): Promise<StudioToolResult> {
if (!input.concept?.trim() || !input.code?.trim()) {
throw new Error('Render tool requires non-empty "concept" and "code"')
}
const jobId = uuidv4()
const outputMode = input.outputMode ?? 'video'
const quality = input.quality ?? 'medium'
await storeJobStage(jobId, 'rendering')
await videoQueue.add(
{
jobId,
concept: input.concept,
outputMode,
quality,
preGeneratedCode: input.code,
customApiConfig: input.customApiConfig,
timestamp: new Date().toISOString(),
workspaceDirectory: context.session.directory
},
{
jobId,
timeout: resolveJobTimeoutMs()
}
)
const lifecycleMetadata = {
concept: input.concept,
outputMode,
quality,
jobId
}
const title = `Render: ${input.concept.slice(0, 80)}`
const { work, task } = await createWorkAndTask({
context,
work: {
sessionId: context.session.id,
runId: context.run.id,
type: 'video',
title,
status: 'queued',
metadata: lifecycleMetadata
},
task: {
sessionId: context.session.id,
runId: context.run.id,
type: 'render',
status: 'queued',
title,
detail: input.concept,
metadata: {
jobId,
outputMode,
quality
}
},
workMetadata: lifecycleMetadata
})
return {
title: `Render queued ${jobId}`,
output: `render_job_id: ${jobId}`,
metadata: {
jobId,
taskId: task?.id,
workId: work?.id,
outputMode,
quality
}
}
}
|