import type { ExecutorType, NodeRuntimeConfig } from "../../../../worker/src/contracts/execution-context.ts"; export type DeliveryNodeDefinition = { id: string; name: string; category: "Source" | "Transform" | "Inspect" | "Annotate" | "Export" | "Utility"; description: string; defaultExecutorType?: ExecutorType; defaultExecutorConfig?: Record; supportsCodeHook?: boolean; allowsMultipleIncoming?: boolean; }; const DEFAULT_DOCKER_EXECUTOR_CONFIG = { image: "python:3.11-alpine", networkMode: "none", } as const; function createDockerDefaults(): Pick { return { defaultExecutorType: "docker", defaultExecutorConfig: { ...DEFAULT_DOCKER_EXECUTOR_CONFIG }, }; } export const DELIVERY_NODE_DEFINITIONS: readonly DeliveryNodeDefinition[] = [ { id: "source-asset", name: "Source Asset", category: "Source", description: "Load the uploaded asset or registered path into the workflow.", ...createDockerDefaults(), }, { id: "extract-archive", name: "Extract Archive", category: "Transform", description: "Unpack tar, zip, or zst archives for downstream processing.", ...createDockerDefaults(), supportsCodeHook: true, }, { id: "rename-folder", name: "Rename Delivery Folder", category: "Transform", description: "Rename the top-level folder to the delivery naming convention.", ...createDockerDefaults(), supportsCodeHook: true, }, { id: "validate-structure", name: "Validate Structure", category: "Inspect", description: "Check required directories and metadata files.", ...createDockerDefaults(), supportsCodeHook: true, }, { id: "validate-metadata", name: "Validate Metadata", category: "Inspect", description: "Validate meta.json, intrinsics.json, and video_meta.json.", ...createDockerDefaults(), supportsCodeHook: true, }, { id: "union-assets", name: "Union Assets", category: "Utility", description: "Merge multiple upstream asset sets into one deduplicated asset set.", ...createDockerDefaults(), supportsCodeHook: true, allowsMultipleIncoming: true, }, { id: "intersect-assets", name: "Intersect Assets", category: "Utility", description: "Keep only the assets that exist in every upstream asset set.", ...createDockerDefaults(), supportsCodeHook: true, allowsMultipleIncoming: true, }, { id: "difference-assets", name: "Difference Assets", category: "Utility", description: "Subtract downstream asset sets from the first upstream asset set.", ...createDockerDefaults(), supportsCodeHook: true, allowsMultipleIncoming: true, }, { id: "export-delivery-package", name: "Export Delivery Package", category: "Export", description: "Publish the normalized package for downstream upload or handoff.", ...createDockerDefaults(), }, ] as const; const DELIVERY_NODE_DEFINITION_BY_ID = new Map( DELIVERY_NODE_DEFINITIONS.map((definition) => [definition.id, definition]), ); export function getDeliveryNodeDefinition(definitionId: string) { return DELIVERY_NODE_DEFINITION_BY_ID.get(definitionId); } export function buildDefaultNodeRuntimeConfig(definitionId: string): NodeRuntimeConfig | undefined { const definition = getDeliveryNodeDefinition(definitionId); if (!definition) { return undefined; } const config: NodeRuntimeConfig = {}; if (definition.defaultExecutorType) { config.executorType = definition.defaultExecutorType; } if (definition.defaultExecutorConfig) { config.executorConfig = { ...definition.defaultExecutorConfig }; } return Object.keys(config).length > 0 ? config : undefined; } export function deliveryNodeAllowsMultipleIncoming(definitionId: string) { return Boolean(getDeliveryNodeDefinition(definitionId)?.allowsMultipleIncoming); }