feat: expose graph still workflow in editor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import api from './client'
|
||||
|
||||
export type WorkflowPresetType = 'still' | 'turntable' | 'multi_angle' | 'still_with_exports' | 'custom'
|
||||
export type WorkflowPresetType = 'still' | 'still_graph' | 'turntable' | 'multi_angle' | 'still_with_exports' | 'custom'
|
||||
export type WorkflowExecutionMode = 'legacy' | 'graph' | 'shadow'
|
||||
|
||||
export interface WorkflowDefinition {
|
||||
@@ -21,6 +21,7 @@ export interface WorkflowConfig {
|
||||
|
||||
export interface WorkflowParams {
|
||||
[key: string]: unknown
|
||||
use_custom_render_settings?: boolean
|
||||
render_engine?: 'cycles' | 'eevee'
|
||||
samples?: number
|
||||
resolution?: [number, number]
|
||||
@@ -53,6 +54,7 @@ export interface WorkflowEdge {
|
||||
export interface WorkflowUi {
|
||||
preset?: WorkflowPresetType
|
||||
execution_mode?: WorkflowExecutionMode
|
||||
blueprint?: string
|
||||
}
|
||||
|
||||
export interface WorkflowCreate {
|
||||
@@ -67,6 +69,7 @@ export interface WorkflowRun {
|
||||
workflow_def_id: string | null
|
||||
order_line_id: string | null
|
||||
celery_task_id: string | null
|
||||
execution_mode: WorkflowExecutionMode
|
||||
status: 'pending' | 'running' | 'completed' | 'failed'
|
||||
started_at: string | null
|
||||
completed_at: string | null
|
||||
@@ -85,6 +88,84 @@ export interface WorkflowNodeResult {
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface WorkflowDispatchResponse {
|
||||
workflow_run: WorkflowRun
|
||||
context_id: string
|
||||
execution_mode: WorkflowExecutionMode
|
||||
dispatched: number
|
||||
task_ids: string[]
|
||||
}
|
||||
|
||||
export interface WorkflowPreflightIssue {
|
||||
severity: 'error' | 'warning' | 'info'
|
||||
code: string
|
||||
message: string
|
||||
node_id: string | null
|
||||
step: string | null
|
||||
}
|
||||
|
||||
export interface WorkflowPreflightNode {
|
||||
node_id: string
|
||||
step: string
|
||||
label: string | null
|
||||
execution_kind: WorkflowNodeExecutionKind
|
||||
supported: boolean
|
||||
status: 'ready' | 'warning' | 'error' | 'unsupported'
|
||||
issues: WorkflowPreflightIssue[]
|
||||
}
|
||||
|
||||
export interface WorkflowPreflightResponse {
|
||||
workflow_id: string | null
|
||||
context_id: string
|
||||
context_kind: 'order_line' | 'cad_file' | null
|
||||
expected_context_kind: 'order_line' | 'cad_file'
|
||||
execution_mode: WorkflowExecutionMode
|
||||
graph_dispatch_allowed: boolean
|
||||
summary: string
|
||||
resolved_order_line_id: string | null
|
||||
resolved_cad_file_id: string | null
|
||||
unsupported_node_ids: string[]
|
||||
issues: WorkflowPreflightIssue[]
|
||||
nodes: WorkflowPreflightNode[]
|
||||
}
|
||||
|
||||
export interface WorkflowDraftPreflightRequest {
|
||||
workflow_id?: string | null
|
||||
context_id: string
|
||||
config: WorkflowConfig
|
||||
}
|
||||
|
||||
export interface WorkflowDraftDispatchRequest {
|
||||
workflow_id?: string | null
|
||||
context_id: string
|
||||
config: WorkflowConfig
|
||||
}
|
||||
|
||||
export interface WorkflowComparisonArtifact {
|
||||
path: string | null
|
||||
storage_key: string | null
|
||||
exists: boolean
|
||||
file_size_bytes: number | null
|
||||
sha256: string | null
|
||||
mime_type: string | null
|
||||
image_width: number | null
|
||||
image_height: number | null
|
||||
}
|
||||
|
||||
export interface WorkflowRunComparison {
|
||||
workflow_run_id: string
|
||||
workflow_def_id: string | null
|
||||
order_line_id: string | null
|
||||
execution_mode: WorkflowExecutionMode
|
||||
status: string
|
||||
summary: string
|
||||
authoritative_output: WorkflowComparisonArtifact
|
||||
observer_output: WorkflowComparisonArtifact
|
||||
exact_match: boolean | null
|
||||
dimensions_match: boolean | null
|
||||
mean_pixel_delta: number | null
|
||||
}
|
||||
|
||||
export const getWorkflows = (): Promise<WorkflowDefinition[]> =>
|
||||
api.get('/workflows').then(r => r.data.map(normalizeWorkflowDefinition))
|
||||
|
||||
@@ -103,10 +184,35 @@ export const deleteWorkflow = (id: string): Promise<void> =>
|
||||
export const getWorkflowRuns = (workflowId: string): Promise<WorkflowRun[]> =>
|
||||
api.get(`/workflows/${workflowId}/runs`).then(r => r.data)
|
||||
|
||||
export const dispatchWorkflow = (
|
||||
workflowId: string,
|
||||
contextId: string,
|
||||
): Promise<WorkflowDispatchResponse> =>
|
||||
api.post(`/workflows/${workflowId}/dispatch`, undefined, { params: { context_id: contextId } }).then(r => r.data)
|
||||
|
||||
export const dispatchWorkflowDraft = (
|
||||
data: WorkflowDraftDispatchRequest,
|
||||
): Promise<WorkflowDispatchResponse> =>
|
||||
api.post('/workflows/dispatch', data).then(r => r.data)
|
||||
|
||||
export const preflightWorkflow = (
|
||||
workflowId: string,
|
||||
contextId: string,
|
||||
): Promise<WorkflowPreflightResponse> =>
|
||||
api.get(`/workflows/${workflowId}/preflight`, { params: { context_id: contextId } }).then(r => r.data)
|
||||
|
||||
export const preflightWorkflowDraft = (
|
||||
data: WorkflowDraftPreflightRequest,
|
||||
): Promise<WorkflowPreflightResponse> =>
|
||||
api.post('/workflows/preflight', data).then(r => r.data)
|
||||
|
||||
export const getWorkflowRunComparison = (runId: string): Promise<WorkflowRunComparison> =>
|
||||
api.get(`/workflows/runs/${runId}/comparison`).then(r => r.data)
|
||||
|
||||
// ─── Node Definitions / Pipeline Steps ───────────────────────────────────────
|
||||
|
||||
export type StepCategory = 'input' | 'processing' | 'rendering' | 'output'
|
||||
export type WorkflowNodeFieldType = 'number' | 'select' | 'boolean'
|
||||
export type WorkflowNodeFieldType = 'number' | 'select' | 'boolean' | 'text'
|
||||
export type WorkflowNodeExecutionKind = 'native' | 'bridge'
|
||||
|
||||
export interface WorkflowNodeFieldOption {
|
||||
@@ -189,6 +295,40 @@ function migratePresetConfig(type: WorkflowPresetType, params: WorkflowParams =
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'still_graph') {
|
||||
return {
|
||||
version: 1,
|
||||
ui: { preset: type, execution_mode: 'graph' },
|
||||
nodes: [
|
||||
{ id: 'setup', step: 'order_line_setup', params: {}, ui: { label: 'Order Line Setup', position: { x: 0, y: 100 } } },
|
||||
{
|
||||
id: 'populate_materials',
|
||||
step: 'auto_populate_materials',
|
||||
params: {},
|
||||
ui: { type: 'processNode', label: 'Auto Populate Materials', position: { x: 220, y: 100 } },
|
||||
},
|
||||
{ id: 'template', step: 'resolve_template', params: {}, ui: { label: 'Resolve Template', position: { x: 440, y: 100 } } },
|
||||
{
|
||||
id: 'resolve_materials',
|
||||
step: 'material_map_resolve',
|
||||
params: {},
|
||||
ui: { type: 'processNode', label: 'Resolve Material Map', position: { x: 660, y: 100 } },
|
||||
},
|
||||
{ id: 'render', step: 'blender_still', params: renderParams, ui: { type: 'renderNode', label: 'Still Render', position: { x: 880, y: 100 } } },
|
||||
{ id: 'output', step: 'output_save', params: {}, ui: { type: 'outputNode', label: 'Save Output', position: { x: 1100, y: 70 } } },
|
||||
{ id: 'notify', step: 'notify', params: {}, ui: { type: 'outputNode', label: 'Notify Result', position: { x: 1100, y: 160 } } },
|
||||
],
|
||||
edges: [
|
||||
{ from: 'setup', to: 'populate_materials' },
|
||||
{ from: 'populate_materials', to: 'template' },
|
||||
{ from: 'template', to: 'resolve_materials' },
|
||||
{ from: 'resolve_materials', to: 'render' },
|
||||
{ from: 'render', to: 'output' },
|
||||
{ from: 'render', to: 'notify' },
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'turntable') {
|
||||
return {
|
||||
version: 1,
|
||||
|
||||
Reference in New Issue
Block a user