@yiyi_zhang/reactflow-ui 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -46
- package/dist/WorkflowIDE.d.ts +9 -1
- package/dist/components/AICopilot/DiffCard.d.ts +10 -0
- package/dist/components/ConfirmDialog.d.ts +1 -1
- package/dist/components/ExecutionTaskPanel.d.ts +6 -2
- package/dist/components/FullscreenEditor.d.ts +23 -0
- package/dist/components/PromptDialog.d.ts +17 -0
- package/dist/components/nodes/DynamicPlaceholderNode.d.ts +5 -0
- package/dist/components/nodes/NodeWrapper.d.ts +3 -1
- package/dist/components/nodes/PlusNode.d.ts +3 -0
- package/dist/config/taskTypes.d.ts +8 -1
- package/dist/hooks/useNodeExecution.d.ts +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/layout/autoLayout.d.ts +1 -1
- package/dist/parser/conductorGenerator.d.ts +8 -0
- package/dist/reactflow-ui.css +1 -1
- package/dist/reactflow-ui.es.js +9702 -7633
- package/dist/reactflow-ui.umd.js +54 -196
- package/dist/sample-executions/fork-dynamic.json +186 -0
- package/dist/sample-executions/human-approval.json +138 -0
- package/dist/sample-executions/loop-iterations.json +221 -0
- package/dist/sample-executions/mixed-status.json +159 -0
- package/dist/sample-executions/retry-tasks.json +160 -0
- package/dist/sample-executions/switch-branches.json +173 -0
- package/dist/types/conductor.d.ts +20 -1
- package/dist/types/workflow.d.ts +132 -4
- package/dist/utils/nodeMeta.d.ts +11 -0
- package/dist/utils/simulateWorkflow.d.ts +8 -0
- package/dist/utils/validationRules.d.ts +25 -0
- package/dist/utils/workflowDiff.d.ts +15 -0
- package/package.json +2 -2
package/dist/types/workflow.d.ts
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
import { Node, Edge, Position } from 'reactflow';
|
|
2
2
|
import { WorkflowDef, TaskDef, WorkflowInstance, TaskInstance } from './conductor';
|
|
3
|
+
/**
|
|
4
|
+
* 视图详情级别(独立于编辑模式)
|
|
5
|
+
* - `business`:仅展示核心业务节点,控制/数据节点折叠为边标签
|
|
6
|
+
* - `standard`:业务 + 控制流节点
|
|
7
|
+
* - `developer`:全部节点(含数据转换等)
|
|
8
|
+
*/
|
|
9
|
+
export type ViewMode = 'business' | 'standard' | 'developer';
|
|
10
|
+
export interface WorkflowDiffRow {
|
|
11
|
+
kind: 'add' | 'mod' | 'del';
|
|
12
|
+
desc: string;
|
|
13
|
+
}
|
|
14
|
+
export type WorkflowPatchOp = {
|
|
15
|
+
op: 'patchTask';
|
|
16
|
+
ref: string;
|
|
17
|
+
set: Partial<TaskDef>;
|
|
18
|
+
} | {
|
|
19
|
+
op: 'insertAfter';
|
|
20
|
+
after: string;
|
|
21
|
+
edgeTo: string;
|
|
22
|
+
task: TaskDef;
|
|
23
|
+
} | {
|
|
24
|
+
op: 'insertBefore';
|
|
25
|
+
before: string;
|
|
26
|
+
task: TaskDef;
|
|
27
|
+
} | {
|
|
28
|
+
op: 'addTask';
|
|
29
|
+
task: TaskDef;
|
|
30
|
+
extraEdges?: Array<{
|
|
31
|
+
from: string;
|
|
32
|
+
to: string;
|
|
33
|
+
label?: string;
|
|
34
|
+
}>;
|
|
35
|
+
removeEdges?: Array<{
|
|
36
|
+
from: string;
|
|
37
|
+
to: string;
|
|
38
|
+
}>;
|
|
39
|
+
} | {
|
|
40
|
+
op: 'removeTask';
|
|
41
|
+
ref: string;
|
|
42
|
+
} | {
|
|
43
|
+
op: 'addEdge';
|
|
44
|
+
from: string;
|
|
45
|
+
to: string;
|
|
46
|
+
label?: string;
|
|
47
|
+
} | {
|
|
48
|
+
op: 'removeEdge';
|
|
49
|
+
from: string;
|
|
50
|
+
to: string;
|
|
51
|
+
};
|
|
52
|
+
export interface WorkflowDiff {
|
|
53
|
+
kind: 'add' | 'mod' | 'del' | 'replace';
|
|
54
|
+
summary: string;
|
|
55
|
+
rows: WorkflowDiffRow[];
|
|
56
|
+
patch?: WorkflowPatchOp[];
|
|
57
|
+
payload?: WorkflowDef;
|
|
58
|
+
}
|
|
59
|
+
export interface AIChatMessage {
|
|
60
|
+
id: string;
|
|
61
|
+
role: 'user' | 'ai';
|
|
62
|
+
content?: string;
|
|
63
|
+
thinking?: boolean;
|
|
64
|
+
diff?: WorkflowDiff;
|
|
65
|
+
applied?: boolean;
|
|
66
|
+
inverse?: WorkflowDiff;
|
|
67
|
+
}
|
|
3
68
|
/**
|
|
4
69
|
* 布局方向
|
|
5
70
|
*/
|
|
@@ -25,6 +90,7 @@ export interface TaskExecutionData {
|
|
|
25
90
|
input?: any;
|
|
26
91
|
reasonForIncompletion?: string;
|
|
27
92
|
iteration?: number;
|
|
93
|
+
totalIterations?: number;
|
|
28
94
|
}
|
|
29
95
|
/**
|
|
30
96
|
* 解析结果
|
|
@@ -34,7 +100,6 @@ export interface ParserResult {
|
|
|
34
100
|
edges: Edge[];
|
|
35
101
|
taskMap: Record<string, TaskDef>;
|
|
36
102
|
nextId: number;
|
|
37
|
-
joinNodeId?: string;
|
|
38
103
|
}
|
|
39
104
|
/**
|
|
40
105
|
* 校验条目
|
|
@@ -71,6 +136,13 @@ export interface WorkflowNodeData {
|
|
|
71
136
|
decisionCases?: Record<string, TaskDef[]>;
|
|
72
137
|
sourcePosition?: Position;
|
|
73
138
|
targetPosition?: Position;
|
|
139
|
+
parentRef?: string;
|
|
140
|
+
edgeData?: Record<string, any>;
|
|
141
|
+
isDynamicRuntime?: boolean;
|
|
142
|
+
simRunning?: boolean;
|
|
143
|
+
simDone?: boolean;
|
|
144
|
+
_layoutWidth?: number;
|
|
145
|
+
_layoutHeight?: number;
|
|
74
146
|
}
|
|
75
147
|
/**
|
|
76
148
|
* 强类型节点
|
|
@@ -93,6 +165,7 @@ export type ThemeColor = 'blue' | 'orange';
|
|
|
93
165
|
*/
|
|
94
166
|
export interface WorkflowState {
|
|
95
167
|
mode: EditorMode;
|
|
168
|
+
viewMode: ViewMode;
|
|
96
169
|
workflowDef: WorkflowDef | null;
|
|
97
170
|
workflowInstance: WorkflowInstance | null;
|
|
98
171
|
nodes: WorkflowNode[];
|
|
@@ -102,6 +175,7 @@ export interface WorkflowState {
|
|
|
102
175
|
selectedTask: TaskDef | null;
|
|
103
176
|
selectedTaskInstance: TaskInstance | null;
|
|
104
177
|
executionData: Record<string, TaskExecutionData> | null;
|
|
178
|
+
dynamicRuntimeTasksByFork: Record<string, TaskInstance[]>;
|
|
105
179
|
validationResults: ValidationResults;
|
|
106
180
|
theme: ThemeMode;
|
|
107
181
|
themeColor: ThemeColor;
|
|
@@ -109,6 +183,10 @@ export interface WorkflowState {
|
|
|
109
183
|
nodesLocked: boolean;
|
|
110
184
|
copiedTask: TaskDef | null;
|
|
111
185
|
isDetailPanelOpen: boolean;
|
|
186
|
+
simState: Record<string, 'idle' | 'running' | 'done'>;
|
|
187
|
+
isSimRunning: boolean;
|
|
188
|
+
/** 每次 setWorkflow() 调用时递增,用于触发 WorkflowDesigner 的 fitView */
|
|
189
|
+
workflowLoadKey: number;
|
|
112
190
|
}
|
|
113
191
|
/**
|
|
114
192
|
* 工作流操作接口
|
|
@@ -135,6 +213,7 @@ export interface WorkflowActions {
|
|
|
135
213
|
removeLoopTask: (loopRef: string, taskRef: string) => void;
|
|
136
214
|
addDecisionBranch: (taskRef: string, caseName: string) => void;
|
|
137
215
|
removeDecisionBranch: (taskRef: string, caseName: string) => void;
|
|
216
|
+
renameDecisionBranch: (taskRef: string, oldName: string, newName: string) => void;
|
|
138
217
|
addForkBranch: (taskRef: string) => void;
|
|
139
218
|
copyTask: (task: TaskDef) => void;
|
|
140
219
|
pasteTask: (task: TaskDef) => void;
|
|
@@ -146,18 +225,67 @@ export interface WorkflowActions {
|
|
|
146
225
|
applyAIGeneratedWorkflow: (workflowJson: any) => void;
|
|
147
226
|
setIsDetailPanelOpen: (isOpen: boolean) => void;
|
|
148
227
|
selectTaskAction: (task: TaskDef | null, openPanel?: boolean) => void;
|
|
228
|
+
setViewMode: (viewMode: ViewMode) => void;
|
|
229
|
+
startSimulation: () => void;
|
|
230
|
+
stopSimulation: () => void;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* 重启选项
|
|
234
|
+
* - `useLatestDef: true` 使用当前最新工作流定义版本重启
|
|
235
|
+
* - `useLatestDef: false` 使用本次执行时的定义版本重启(默认)
|
|
236
|
+
*/
|
|
237
|
+
export interface RestartOptions {
|
|
238
|
+
useLatestDef?: boolean;
|
|
149
239
|
}
|
|
150
240
|
/**
|
|
151
241
|
* 运行态操作回调
|
|
152
|
-
*
|
|
153
|
-
*
|
|
242
|
+
* 集成方通过此接口注入工作流执行操作的回调函数;未传入的回调对应的按钮不会渲染。
|
|
243
|
+
*
|
|
244
|
+
* 工作流级别操作:暂停、继续、终止、重试、重新运行(支持版本选择)
|
|
245
|
+
* 任务级别操作:从指定任务重新运行、跳过任务
|
|
154
246
|
*/
|
|
155
247
|
export interface ExecutionActions {
|
|
156
|
-
|
|
248
|
+
/**
|
|
249
|
+
* 是否允许操作。
|
|
250
|
+
* - `true`(默认):所有操作按钮正常可用。
|
|
251
|
+
* - `false`:所有操作按钮置灰并提示"操作权限受限"。
|
|
252
|
+
* @default true
|
|
253
|
+
*/
|
|
254
|
+
allowOperations?: boolean;
|
|
255
|
+
/** 暂停工作流(RUNNING → PAUSED) */
|
|
157
256
|
onPause?: (workflowId: string) => void;
|
|
257
|
+
/** 继续执行暂停中的工作流(PAUSED → RUNNING) */
|
|
158
258
|
onResume?: (workflowId: string) => void;
|
|
259
|
+
/** 终止工作流(RUNNING/PAUSED → TERMINATED) */
|
|
159
260
|
onTerminate?: (workflowId: string) => void;
|
|
261
|
+
/** 重试失败的工作流(FAILED/TIMED_OUT/TERMINATED) */
|
|
160
262
|
onRetry?: (workflowId: string) => void;
|
|
263
|
+
/**
|
|
264
|
+
* 重新运行工作流(需要 workflowDef.restartable = true)
|
|
265
|
+
* @param options.useLatestDef true=使用最新定义版本;false=使用执行时的版本(默认)
|
|
266
|
+
*/
|
|
267
|
+
onRestart?: (workflowId: string, options?: RestartOptions) => void;
|
|
268
|
+
/**
|
|
269
|
+
* 从指定任务重新运行(工作流须处于终态:FAILED/TERMINATED/COMPLETED)
|
|
270
|
+
*
|
|
271
|
+
* 对应 Conductor OSS API:POST /workflow/{workflowId}/rerun
|
|
272
|
+
* - body: { reRunFromTaskId: taskId, taskInput: {} }
|
|
273
|
+
*
|
|
274
|
+
* @param workflowId 工作流实例 ID
|
|
275
|
+
* @param taskReferenceName 目标任务的引用名(taskReferenceName)
|
|
276
|
+
* @param taskId 目标任务实例 ID(对应 Conductor API 的 reRunFromTaskId)
|
|
277
|
+
*/
|
|
278
|
+
onRerunFromTask?: (workflowId: string, taskReferenceName: string, taskId?: string) => void;
|
|
279
|
+
/**
|
|
280
|
+
* 跳过指定任务(任务须处于 SCHEDULED 或 IN_PROGRESS 状态)
|
|
281
|
+
*
|
|
282
|
+
* 对应 Conductor OSS API:PUT /workflow/{workflowId}/skiptask/{taskReferenceName}
|
|
283
|
+
*
|
|
284
|
+
* @param workflowId 工作流实例 ID
|
|
285
|
+
* @param taskReferenceName 目标任务的引用名(URL path 参数)
|
|
286
|
+
* @param taskId 目标任务实例 ID(可用于请求体附加校验)
|
|
287
|
+
*/
|
|
288
|
+
onSkipTask?: (workflowId: string, taskReferenceName: string, taskId?: string) => void;
|
|
161
289
|
}
|
|
162
290
|
/**
|
|
163
291
|
* 组合 Store 类型
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ViewMode, WorkflowNodeData } from '../types/workflow';
|
|
2
|
+
declare function truncate(s: string, max: number): string;
|
|
3
|
+
/**
|
|
4
|
+
* Returns the meta subtitle for a node based on the current viewMode.
|
|
5
|
+
* - business: task.description (fallback to label)
|
|
6
|
+
* - standard: unchanged (returns fallback)
|
|
7
|
+
* - developer: key config field for the task type
|
|
8
|
+
*/
|
|
9
|
+
export declare function getNodeMeta(taskType: string, data: WorkflowNodeData, viewMode: ViewMode, fallback: string): string;
|
|
10
|
+
/** Truncate helper exported for use in node components (e.g. DecisionNode). */
|
|
11
|
+
export { truncate };
|
|
@@ -36,6 +36,12 @@ export declare const TASK_RULES: {
|
|
|
36
36
|
level: string;
|
|
37
37
|
message: string;
|
|
38
38
|
})[];
|
|
39
|
+
INLINE: {
|
|
40
|
+
field: string;
|
|
41
|
+
type: string;
|
|
42
|
+
validate: (_val: any, task: any) => boolean;
|
|
43
|
+
message: string;
|
|
44
|
+
}[];
|
|
39
45
|
LAMBDA: {
|
|
40
46
|
field: string;
|
|
41
47
|
type: string;
|
|
@@ -51,6 +57,17 @@ export declare const TASK_RULES: {
|
|
|
51
57
|
type: string;
|
|
52
58
|
message: string;
|
|
53
59
|
}[];
|
|
60
|
+
START_WORKFLOW: {
|
|
61
|
+
field: string;
|
|
62
|
+
type: string;
|
|
63
|
+
validate: (_val: any, task: any) => boolean;
|
|
64
|
+
message: string;
|
|
65
|
+
}[];
|
|
66
|
+
DYNAMIC: {
|
|
67
|
+
field: string;
|
|
68
|
+
type: string;
|
|
69
|
+
message: string;
|
|
70
|
+
}[];
|
|
54
71
|
TERMINATE: ({
|
|
55
72
|
field: string;
|
|
56
73
|
type: string;
|
|
@@ -67,6 +84,7 @@ export declare const TASK_RULES: {
|
|
|
67
84
|
DO_WHILE: {
|
|
68
85
|
field: string;
|
|
69
86
|
type: string;
|
|
87
|
+
validate: (_val: any, task: any) => boolean;
|
|
70
88
|
message: string;
|
|
71
89
|
}[];
|
|
72
90
|
DECISION: {
|
|
@@ -81,5 +99,12 @@ export declare const TASK_RULES: {
|
|
|
81
99
|
validate: (val: any) => boolean;
|
|
82
100
|
message: string;
|
|
83
101
|
}[];
|
|
102
|
+
FORK_JOIN_DYNAMIC: {
|
|
103
|
+
field: string;
|
|
104
|
+
type: string;
|
|
105
|
+
validate: (_val: any, task: any) => boolean;
|
|
106
|
+
message: string;
|
|
107
|
+
level: string;
|
|
108
|
+
}[];
|
|
84
109
|
};
|
|
85
110
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { WorkflowDef } from '../types/conductor';
|
|
2
|
+
import { WorkflowDiff } from '../types/workflow';
|
|
3
|
+
/**
|
|
4
|
+
* 将 WorkflowDiff 应用到 WorkflowDef,返回新的 def 以及用于撤销的逆操作 diff。
|
|
5
|
+
* 不修改入参(深拷贝)。
|
|
6
|
+
*/
|
|
7
|
+
export declare function applyWorkflowDiff(def: WorkflowDef, diff: WorkflowDiff): {
|
|
8
|
+
next: WorkflowDef;
|
|
9
|
+
inverse: WorkflowDiff;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 从 AI 响应文本中提取 ```diff-json ... ``` 块并解析为 WorkflowDiff。
|
|
13
|
+
* 找不到或解析失败时返回 null。
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseDiffFromAIResponse(text: string): WorkflowDiff | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yiyi_zhang/reactflow-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Conductor Workflow IDE — a visual workflow designer built with React 19, ReactFlow and Zustand for editing, validating and monitoring Netflix Conductor workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"conductor",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
],
|
|
37
37
|
"scripts": {
|
|
38
38
|
"dev": "vite",
|
|
39
|
-
"build": "
|
|
39
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
40
40
|
"lint": "eslint .",
|
|
41
41
|
"preview": "vite preview"
|
|
42
42
|
},
|