import { Field, type WorkflowNodeRegistry, useNodeRender } from "@flowgram.ai/free-layout-editor" import type { AIWorkflowNodeSpec } from "@/lib/api/admin" import { WorkflowConditionNodeContent } from "./workflow-condition-node-content" import { WorkflowNodeCard } from "./workflow-node-card" import { WorkflowSimpleNodeContent } from "./workflow-simple-node-content" export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): WorkflowNodeRegistry[] { const seen = new Set() const specs = nodeSpecs.length > 0 ? nodeSpecs : [ { type: "start", title: "开始", description: "流程入口", riskLevel: "low" as const, interruptible: false, requiresConfirmationPredecessor: false, }, { type: "end", title: "结束", description: "流程结束", riskLevel: "low" as const, interruptible: false, requiresConfirmationPredecessor: false, }, ] return specs .filter((spec) => { if (!spec.type || seen.has(spec.type)) { return false } seen.add(spec.type) return true }) .map((spec) => ({ type: spec.type, meta: { defaultExpanded: true, isStart: spec.type === "start", deleteDisable: spec.type === "start" || spec.type === "end", copyDisable: spec.type === "start" || spec.type === "end", defaultPorts: defaultPortsForNodeType(spec.type), }, formMeta: { render: () => ( ), }, })) } function FlowgramNodeForm({ nodeType, fallbackTitle, spec, }: { nodeType: string fallbackTitle: string spec?: AIWorkflowNodeSpec }) { const { node, selected } = useNodeRender() const nodeId = String(node.id ?? "") return ( name="title"> {({ field }) => ( {nodeType === "condition" ? ( > name="config"> {({ field: configField }) => ( )} ) : ( )} )} ) } function defaultPortsForNodeType(type: string) { if (type === "start") { return [{ type: "output" as const }] } if (type === "end") { return [{ type: "input" as const }] } if (type === "condition") { return [{ type: "input" as const }] } return [{ type: "input" as const }, { type: "output" as const }] }