// Package dsl 把前端导出的 JSON DSL 图编译为可执行的对话计划。 // 当前从图中抽取「系统提示词 / 用户输入 / 工具节点」;后续可演进为 // compose.NewGraph 的完整多节点编译(分支/并行/工具节点逐一映射)。 package dsl import ( "encoding/json" "fmt" "strings" ) // Node 是 DSL 图的一个节点(与前端 exportDsl 对齐)。 type Node struct { ID string `json:"id"` Kind string `json:"kind"` Label string `json:"label"` Config map[string]any `json:"config"` } // Edge 是一条连线。 type Edge struct { Source string `json:"source"` Target string `json:"target"` } // Flow 是整张图。 type Flow struct { Version string `json:"version"` Nodes []Node `json:"nodes"` Edges []Edge `json:"edges"` } // Plan 是编译后的对话计划。 type Plan struct { System string // 系统提示词(来自 agent 节点的 system;空则默认) Query string // 用户输入(来自 input 节点 text / agent 节点 prompt) Tools []string // 图中工具节点绑定的 MCP 工具名(供后续工具编排用) } const defaultSystem = "你是 sundynix-agentix 平台的 AI 助手。" // Compile 解析 DSL 图,抽取对话计划。无法解析时退化为把原文当输入(兼容旧行为)。 func Compile(graph json.RawMessage) Plan { var f Flow if err := json.Unmarshal(graph, &f); err != nil || len(f.Nodes) == 0 { return Plan{System: defaultSystem, Query: strings.TrimSpace(string(graph))} } var queries, systems, tools []string for _, n := range f.Nodes { switch n.Kind { case "input": if t := str(n.Config["text"]); t != "" { queries = append(queries, t) } case "agent": if s := str(n.Config["system"]); s != "" { systems = append(systems, s) } if p := str(n.Config["prompt"]); p != "" { // 单 agent 节点快速测试时直接带 prompt queries = append(queries, p) } case "tool": if t := str(n.Config["tool"]); t != "" { tools = append(tools, t) } } } system := strings.Join(systems, "\n") if system == "" { system = defaultSystem } query := strings.Join(queries, "\n") if query == "" { query = "你好" // 无结构化输入时的兜底,避免给模型发空消息 } return Plan{System: system, Query: query, Tools: tools} } func str(v any) string { if v == nil { return "" } if s, ok := v.(string); ok { return strings.TrimSpace(s) } return strings.TrimSpace(fmt.Sprint(v)) }