Add Dify integration and enhance workflow node specifications

- Introduce new fields `dify_api_url` and `dify_api_key` in `AssistantConfig` for Dify API integration.
- Update `requirements.txt` to include `dify-client-python` for Dify SDK support.
- Modify `config_resolver` to handle Dify connection information.
- Add a new `globalNode` type in workflow specifications to provide unified settings across workflows.
- Enhance node specifications with additional constraints and default values for better configuration management.
- Update frontend components to support the new `globalNode` type and its properties, improving workflow editor functionality.
This commit is contained in:
Xin Wang
2026-07-11 22:26:31 +08:00
parent dfb9c5bd11
commit 00270a5c01
23 changed files with 1270 additions and 414 deletions

View File

@@ -11,7 +11,11 @@ import { Circle, type LucideIcon } from "lucide-react";
import type { NodeSpecDto } from "@/lib/api";
export type WorkflowNodeType = "startCall" | "agentNode" | "endCall";
export type WorkflowNodeType =
| "startCall"
| "agentNode"
| "endCall"
| "globalNode";
export type WorkflowNodeData = {
/** 节点显示名 */
@@ -22,6 +26,8 @@ export type WorkflowNodeData = {
prompt?: string;
/** 允许打断(仅 agentNode) */
allowInterrupt?: boolean;
/** 是否合并全局节点提示词(start/agent 默认开启,end 默认关闭) */
addGlobalPrompt?: boolean;
[key: string]: unknown;
};
@@ -30,6 +36,7 @@ export type FieldSpec = {
label: string;
type: "text" | "textarea" | "switch";
required?: boolean;
default?: unknown;
};
/** 解析后的运行期节点规格(DTO + 解析出的 React 图标 + 派生句柄) */
@@ -44,6 +51,14 @@ export type RuntimeNodeSpec = {
hasTarget: boolean;
/** 出边句柄(结束节点没有) */
hasSource: boolean;
constraints: {
minIncoming?: number;
maxIncoming?: number;
minOutgoing?: number;
maxOutgoing?: number;
minInstances?: number;
maxInstances?: number;
};
fields: FieldSpec[];
};
@@ -77,11 +92,13 @@ export function toRuntimeSpec(dto: NodeSpecDto): RuntimeNodeSpec {
addable: dto.addable,
hasTarget: dto.constraints.maxIncoming !== 0,
hasSource: dto.constraints.maxOutgoing !== 0,
constraints: dto.constraints,
fields: dto.fields.map((f) => ({
key: f.key,
label: f.label,
type: f.type,
required: f.required,
default: f.default,
})),
};
}
@@ -104,27 +121,52 @@ export type WorkflowGraph = {
viewport?: { x: number; y: number; zoom: number };
};
/** 新建工作流的默认图:开始 → 智能体 → 结束 */
/** 新建工作流的默认图:全局规则 + 开始 → 智能体 → 结束 */
export function defaultGraph(): WorkflowGraph {
return {
nodes: [
{
id: "start",
type: "startCall",
position: { x: 80, y: 160 },
data: { name: "开始", greeting: "你好,我是 AI 视频助手,有什么可以帮你?" },
position: { x: 100, y: 120 },
data: {
name: "开始",
greeting: "你好,我是 AI 视频助手,有什么可以帮你?",
prompt: "了解用户的需求,并在信息明确后进入下一节点。",
allowInterrupt: true,
addGlobalPrompt: true,
},
},
{
id: "agent-1",
type: "agentNode",
position: { x: 400, y: 160 },
data: { name: "智能体节点", prompt: "", allowInterrupt: true },
position: { x: 420, y: 120 },
data: {
name: "智能体节点",
prompt: "根据用户需求提供清晰、准确的帮助。",
allowInterrupt: true,
addGlobalPrompt: true,
},
},
{
id: "end",
type: "endCall",
position: { x: 720, y: 160 },
data: { name: "结束", prompt: "感谢你的来电,再见!" },
position: { x: 740, y: 120 },
data: {
name: "结束",
prompt: "总结已经完成的事项,礼貌道别并结束通话。",
addGlobalPrompt: false,
},
},
{
id: "global",
type: "globalNode",
position: { x: 100, y: 400 },
data: {
name: "全局设定",
prompt:
"你是一个友好、专业的语音助手。请使用简短、自然、适合口语表达的句子。",
},
},
],
edges: [