"use client"; import type { Edge } from "@xyflow/react"; import { Braces, GitBranch, Plus, Trash2, } from "lucide-react"; import { useState } from "react"; import { SectionCard } from "@/components/editor/section-card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { NodeSelect } from "./controls"; import type { ExpressionRule, WorkflowEdgeData } from "../specs"; export function EdgeSettingsPanel({ edge, sourceType, isOnlyOutgoing, hasOtherDefaultPath, onChange, }: { edge: Edge; sourceType?: string; isOnlyOutgoing: boolean; hasOtherDefaultPath: boolean; onChange: (patch: Partial) => void; }) { const data = (edge.data ?? { mode: "always", priority: 10 }) as WorkflowEdgeData; const [mode, setMode] = useState(data.mode ?? "always"); const [condition, setCondition] = useState(data.condition ?? ""); const [combinator, setCombinator] = useState<"and" | "or">( data.expression?.combinator ?? "and", ); const [rules, setRules] = useState( data.expression?.rules?.length ? data.expression.rules : [{ variable: "", operator: "eq", value: "" }], ); const publish = ({ nextMode = mode, nextCondition = condition, nextCombinator = combinator, nextRules = rules, }: { nextMode?: WorkflowEdgeData["mode"]; nextCondition?: string; nextCombinator?: "and" | "or"; nextRules?: ExpressionRule[]; }) => onChange({ mode: nextMode, condition: nextMode === "llm" ? nextCondition : undefined, expression: nextMode === "expression" ? { combinator: nextCombinator, rules: nextRules } : undefined, }); const setRule = (index: number, patch: Partial) => { const nextRules = rules.map((rule, ruleIndex) => ruleIndex === index ? { ...rule, ...patch } : rule, ); setRules(nextRules); publish({ nextRules }); }; const parseValue = (value: string): unknown => { if (value === "true") return true; if (value === "false") return false; if (value !== "" && Number.isFinite(Number(value))) return Number(value); return value; }; return (
} title="路由方式" description="每个节点最多一条默认路径,也可以配置多条条件路径" > { const nextMode = (value as WorkflowEdgeData["mode"]) || "always"; setMode(nextMode); publish({ nextMode }); }} allowNone={false} /> {mode !== "always" && hasOtherDefaultPath && ( 当前节点已经有一条默认路径;其它出边需要使用大模型判断或表达式。 )} {sourceType === "agent" && isOnlyOutgoing && mode === "always" && ( Agent 不能只有默认路径;请改为条件路径,或删除连接以持续对话。 )} } title="触发条件" description="配置这条连接被命中的条件" > {mode === "llm" && (