feat: make output types workflow-first contracts

This commit is contained in:
2026-04-08 21:43:55 +02:00
parent bd18cccb5e
commit 8c9648d5dc
8 changed files with 1049 additions and 110 deletions
+77
View File
@@ -1,22 +1,56 @@
import api from './client'
export type OutputTypeWorkflowFamily = 'cad_file' | 'order_line'
export type OutputTypeArtifactKind =
| 'still_image'
| 'turntable_video'
| 'model_export'
| 'thumbnail_image'
| 'blend_asset'
| 'package'
| 'custom'
export const OUTPUT_TYPE_INVOCATION_OVERRIDE_KEYS = [
'width',
'height',
'engine',
'samples',
'frame_count',
'fps',
'turntable_axis',
'bg_color',
'noise_threshold',
'denoiser',
'denoising_input_passes',
'denoising_prefilter',
'denoising_quality',
'denoising_use_gpu',
] as const
const CAD_FILE_ARTIFACT_KINDS: OutputTypeArtifactKind[] = ['thumbnail_image', 'model_export', 'package', 'custom']
const ORDER_LINE_ARTIFACT_KINDS: OutputTypeArtifactKind[] = ['still_image', 'turntable_video', 'blend_asset', 'package', 'custom']
export interface OutputType {
id: string
name: string
description: string | null
renderer: string
render_settings: Record<string, unknown>
invocation_overrides: Record<string, unknown>
output_format: string
sort_order: number
compatible_categories: string[]
render_backend: string
is_animation: boolean
transparent_bg: boolean
workflow_family: OutputTypeWorkflowFamily
artifact_kind: OutputTypeArtifactKind
cycles_device: string | null
pricing_tier_id: number | null
pricing_tier_name: string | null
price_per_item: number | null
workflow_definition_id: string | null
workflow_name?: string | null
material_override: string | null
is_active: boolean
created_at: string
@@ -46,3 +80,46 @@ export async function updateOutputType(id: string, data: Partial<OutputType>): P
export async function deleteOutputType(id: string): Promise<void> {
await api.delete(`/output-types/${id}`)
}
export function listAllowedArtifactKindsForFamily(family: OutputTypeWorkflowFamily): OutputTypeArtifactKind[] {
return family === 'cad_file' ? [...CAD_FILE_ARTIFACT_KINDS] : [...ORDER_LINE_ARTIFACT_KINDS]
}
export function inferArtifactKind(
workflowFamily: OutputTypeWorkflowFamily,
outputFormat: string,
isAnimation: boolean,
): OutputTypeArtifactKind {
const normalizedFormat = outputFormat.trim().toLowerCase()
if (isAnimation || ['mp4', 'webm', 'mov'].includes(normalizedFormat)) {
return 'turntable_video'
}
if (['gltf', 'glb', 'stl', 'obj', 'usd', 'usdz'].includes(normalizedFormat)) {
return 'model_export'
}
if (workflowFamily === 'cad_file') {
return 'thumbnail_image'
}
return 'still_image'
}
export function isArtifactKindAllowedForFamily(
workflowFamily: OutputTypeWorkflowFamily,
artifactKind: OutputTypeArtifactKind,
): boolean {
return listAllowedArtifactKindsForFamily(workflowFamily).includes(artifactKind)
}
export function getOutputTypeInvocationOverrides(outputType: OutputType): Record<string, unknown> {
const normalized: Record<string, unknown> = {}
for (const key of OUTPUT_TYPE_INVOCATION_OVERRIDE_KEYS) {
const explicitValue = outputType.invocation_overrides?.[key]
const legacyValue = outputType.render_settings?.[key]
const value = explicitValue ?? legacyValue
if (value !== undefined && value !== null && value !== '') {
normalized[key] = value
}
}
return normalized
}