@marktoflow/gui 2.0.0-alpha.1 → 2.0.0-alpha.13

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.
Files changed (172) hide show
  1. package/README.md +49 -3
  2. package/dist/client/assets/index-CM44OayM.js +704 -0
  3. package/dist/client/assets/index-CM44OayM.js.map +1 -0
  4. package/dist/client/assets/index-Dru63gi6.css +1 -0
  5. package/dist/client/index.html +2 -2
  6. package/dist/server/index.js +93 -33
  7. package/dist/server/index.js.map +1 -1
  8. package/dist/server/routes/ai.js +38 -1
  9. package/dist/server/routes/ai.js.map +1 -1
  10. package/dist/server/routes/execute.js +23 -22
  11. package/dist/server/routes/execute.js.map +1 -1
  12. package/dist/server/routes/executions.js +125 -0
  13. package/dist/server/routes/executions.js.map +1 -0
  14. package/dist/server/{server/routes → routes}/tools.js +406 -0
  15. package/dist/server/{server/routes → routes}/tools.js.map +1 -1
  16. package/dist/server/routes/workflows.js +41 -5
  17. package/dist/server/routes/workflows.js.map +1 -1
  18. package/dist/server/services/AIService.js +55 -202
  19. package/dist/server/services/AIService.js.map +1 -1
  20. package/dist/server/services/FileWatcher.js +0 -2
  21. package/dist/server/services/FileWatcher.js.map +1 -1
  22. package/dist/server/services/WorkflowService.js +199 -16
  23. package/dist/server/services/WorkflowService.js.map +1 -1
  24. package/dist/server/services/agents/codex-provider.js +270 -0
  25. package/dist/server/services/agents/codex-provider.js.map +1 -0
  26. package/dist/server/{server/services → services}/agents/prompts.js +27 -0
  27. package/dist/server/services/agents/prompts.js.map +1 -0
  28. package/dist/server/{server/services → services}/agents/registry.js +20 -0
  29. package/dist/server/services/agents/registry.js.map +1 -0
  30. package/dist/server/websocket/index.js +12 -0
  31. package/dist/server/websocket/index.js.map +1 -1
  32. package/package.json +19 -7
  33. package/scripts/flatten-dist.js +69 -0
  34. package/.turbo/turbo-build.log +0 -26
  35. package/.turbo/turbo-test.log +0 -22
  36. package/dist/client/assets/index-DwTI8opO.js +0 -608
  37. package/dist/client/assets/index-DwTI8opO.js.map +0 -1
  38. package/dist/client/assets/index-RoEdL6gO.css +0 -1
  39. package/dist/server/index.d.ts +0 -3
  40. package/dist/server/index.d.ts.map +0 -1
  41. package/dist/server/server/index.js +0 -95
  42. package/dist/server/server/index.js.map +0 -1
  43. package/dist/server/server/routes/ai.js +0 -87
  44. package/dist/server/server/routes/ai.js.map +0 -1
  45. package/dist/server/server/routes/execute.js +0 -63
  46. package/dist/server/server/routes/execute.js.map +0 -1
  47. package/dist/server/server/routes/workflows.js +0 -99
  48. package/dist/server/server/routes/workflows.js.map +0 -1
  49. package/dist/server/server/services/AIService.js +0 -69
  50. package/dist/server/server/services/AIService.js.map +0 -1
  51. package/dist/server/server/services/FileWatcher.js +0 -60
  52. package/dist/server/server/services/FileWatcher.js.map +0 -1
  53. package/dist/server/server/services/WorkflowService.js +0 -363
  54. package/dist/server/server/services/WorkflowService.js.map +0 -1
  55. package/dist/server/server/services/agents/prompts.js.map +0 -1
  56. package/dist/server/server/services/agents/registry.js.map +0 -1
  57. package/dist/server/server/websocket/index.js +0 -85
  58. package/dist/server/server/websocket/index.js.map +0 -1
  59. package/dist/server/services/AIService.d.ts +0 -30
  60. package/dist/server/services/AIService.d.ts.map +0 -1
  61. package/dist/server/services/FileWatcher.d.ts +0 -10
  62. package/dist/server/services/FileWatcher.d.ts.map +0 -1
  63. package/dist/server/services/WorkflowService.d.ts +0 -54
  64. package/dist/server/services/WorkflowService.d.ts.map +0 -1
  65. package/dist/server/websocket/index.d.ts +0 -10
  66. package/dist/server/websocket/index.d.ts.map +0 -1
  67. package/playwright.config.ts +0 -27
  68. package/postcss.config.js +0 -6
  69. package/src/client/App.tsx +0 -520
  70. package/src/client/components/Canvas/Canvas.tsx +0 -405
  71. package/src/client/components/Canvas/ExecutionOverlay.tsx +0 -847
  72. package/src/client/components/Canvas/NodeContextMenu.tsx +0 -188
  73. package/src/client/components/Canvas/OutputNode.tsx +0 -111
  74. package/src/client/components/Canvas/StepNode.tsx +0 -106
  75. package/src/client/components/Canvas/SubWorkflowNode.tsx +0 -141
  76. package/src/client/components/Canvas/Toolbar.tsx +0 -189
  77. package/src/client/components/Canvas/TriggerNode.tsx +0 -128
  78. package/src/client/components/Editor/InputsEditor.tsx +0 -458
  79. package/src/client/components/Editor/NewStepWizard.tsx +0 -344
  80. package/src/client/components/Editor/StepEditor.tsx +0 -532
  81. package/src/client/components/Editor/YamlEditor.tsx +0 -160
  82. package/src/client/components/Panels/PropertiesPanel.tsx +0 -589
  83. package/src/client/components/Prompt/ChangePreview.tsx +0 -281
  84. package/src/client/components/Prompt/PromptHistoryPanel.tsx +0 -209
  85. package/src/client/components/Prompt/PromptInput.tsx +0 -108
  86. package/src/client/components/Sidebar/Sidebar.tsx +0 -343
  87. package/src/client/components/common/Breadcrumb.tsx +0 -40
  88. package/src/client/components/common/Button.tsx +0 -68
  89. package/src/client/components/common/ContextMenu.tsx +0 -202
  90. package/src/client/components/common/KeyboardShortcuts.tsx +0 -143
  91. package/src/client/components/common/Modal.tsx +0 -93
  92. package/src/client/components/common/Tabs.tsx +0 -57
  93. package/src/client/components/common/ThemeToggle.tsx +0 -63
  94. package/src/client/components/index.ts +0 -32
  95. package/src/client/hooks/index.ts +0 -4
  96. package/src/client/hooks/useAIPrompt.ts +0 -108
  97. package/src/client/hooks/useCanvas.ts +0 -247
  98. package/src/client/hooks/useWebSocket.ts +0 -164
  99. package/src/client/hooks/useWorkflow.ts +0 -138
  100. package/src/client/main.tsx +0 -10
  101. package/src/client/stores/canvasStore.ts +0 -348
  102. package/src/client/stores/editorStore.ts +0 -133
  103. package/src/client/stores/executionStore.ts +0 -440
  104. package/src/client/stores/index.ts +0 -4
  105. package/src/client/stores/layoutStore.ts +0 -103
  106. package/src/client/stores/navigationStore.ts +0 -49
  107. package/src/client/stores/promptStore.ts +0 -113
  108. package/src/client/stores/themeStore.ts +0 -75
  109. package/src/client/stores/workflowStore.ts +0 -177
  110. package/src/client/styles/globals.css +0 -346
  111. package/src/client/utils/cn.ts +0 -9
  112. package/src/client/utils/index.ts +0 -4
  113. package/src/client/utils/serviceIcons.tsx +0 -64
  114. package/src/client/utils/stepValidation.ts +0 -155
  115. package/src/client/utils/workflowToGraph.ts +0 -299
  116. package/src/server/index.ts +0 -114
  117. package/src/server/routes/ai.ts +0 -91
  118. package/src/server/routes/execute.ts +0 -71
  119. package/src/server/routes/tools.ts +0 -564
  120. package/src/server/routes/workflows.ts +0 -106
  121. package/src/server/services/AIService.ts +0 -105
  122. package/src/server/services/FileWatcher.ts +0 -69
  123. package/src/server/services/WorkflowService.ts +0 -441
  124. package/src/server/services/agents/claude-code-provider.ts +0 -320
  125. package/src/server/services/agents/claude-provider.ts +0 -248
  126. package/src/server/services/agents/copilot-provider.ts +0 -311
  127. package/src/server/services/agents/demo-provider.ts +0 -184
  128. package/src/server/services/agents/index.ts +0 -31
  129. package/src/server/services/agents/ollama-provider.ts +0 -267
  130. package/src/server/services/agents/prompts.ts +0 -482
  131. package/src/server/services/agents/registry.ts +0 -289
  132. package/src/server/services/agents/types.ts +0 -146
  133. package/src/server/websocket/index.ts +0 -104
  134. package/src/shared/constants.ts +0 -180
  135. package/src/shared/types.ts +0 -179
  136. package/tailwind.config.ts +0 -73
  137. package/tests/e2e/app.spec.ts +0 -90
  138. package/tests/e2e/canvas.spec.ts +0 -128
  139. package/tests/e2e/workflow.spec.ts +0 -185
  140. package/tests/integration/api.test.ts +0 -250
  141. package/tests/integration/testApp.ts +0 -31
  142. package/tests/setup.ts +0 -37
  143. package/tests/unit/canvasStore.test.ts +0 -502
  144. package/tests/unit/components.test.tsx +0 -151
  145. package/tests/unit/executionStore.test.ts +0 -527
  146. package/tests/unit/layoutStore.test.ts +0 -194
  147. package/tests/unit/navigationStore.test.ts +0 -152
  148. package/tests/unit/stepValidation.test.ts +0 -226
  149. package/tests/unit/themeStore.test.ts +0 -141
  150. package/tests/unit/workflowToGraph.test.ts +0 -289
  151. package/tsconfig.json +0 -29
  152. package/tsconfig.server.json +0 -28
  153. package/vite.config.ts +0 -31
  154. package/vitest.config.ts +0 -26
  155. /package/dist/server/{server/services → services}/agents/claude-code-provider.js +0 -0
  156. /package/dist/server/{server/services → services}/agents/claude-code-provider.js.map +0 -0
  157. /package/dist/server/{server/services → services}/agents/claude-provider.js +0 -0
  158. /package/dist/server/{server/services → services}/agents/claude-provider.js.map +0 -0
  159. /package/dist/server/{server/services → services}/agents/copilot-provider.js +0 -0
  160. /package/dist/server/{server/services → services}/agents/copilot-provider.js.map +0 -0
  161. /package/dist/server/{server/services → services}/agents/demo-provider.js +0 -0
  162. /package/dist/server/{server/services → services}/agents/demo-provider.js.map +0 -0
  163. /package/dist/server/{server/services → services}/agents/index.js +0 -0
  164. /package/dist/server/{server/services → services}/agents/index.js.map +0 -0
  165. /package/dist/server/{server/services → services}/agents/ollama-provider.js +0 -0
  166. /package/dist/server/{server/services → services}/agents/ollama-provider.js.map +0 -0
  167. /package/dist/server/{server/services → services}/agents/types.js +0 -0
  168. /package/dist/server/{server/services → services}/agents/types.js.map +0 -0
  169. /package/dist/{server/shared → shared}/constants.js +0 -0
  170. /package/dist/{server/shared → shared}/constants.js.map +0 -0
  171. /package/dist/{server/shared → shared}/types.js +0 -0
  172. /package/dist/{server/shared → shared}/types.js.map +0 -0
@@ -1,188 +0,0 @@
1
- import {
2
- ContextMenu,
3
- ContextMenuContent,
4
- ContextMenuItem,
5
- ContextMenuSeparator,
6
- ContextMenuSub,
7
- ContextMenuSubContent,
8
- ContextMenuSubTrigger,
9
- ContextMenuShortcut,
10
- } from '../common/ContextMenu';
11
- import {
12
- Edit,
13
- Code,
14
- FileText,
15
- Copy,
16
- Trash2,
17
- Plus,
18
- FolderOpen,
19
- Play,
20
- AlertTriangle,
21
- } from 'lucide-react';
22
- import type { Node } from '@xyflow/react';
23
-
24
- interface NodeContextMenuProps {
25
- children: React.ReactNode;
26
- node: Node;
27
- onEdit: () => void;
28
- onViewYaml: () => void;
29
- onViewDocs: () => void;
30
- onDuplicate: () => void;
31
- onDelete: () => void;
32
- onAddStepBefore: () => void;
33
- onAddStepAfter: () => void;
34
- onConvertToSubworkflow: () => void;
35
- onExecuteFrom: () => void;
36
- }
37
-
38
- export function NodeContextMenu({
39
- children,
40
- node,
41
- onEdit,
42
- onViewYaml,
43
- onViewDocs,
44
- onDuplicate,
45
- onDelete,
46
- onAddStepBefore,
47
- onAddStepAfter,
48
- onConvertToSubworkflow,
49
- onExecuteFrom,
50
- }: NodeContextMenuProps) {
51
- const isSubworkflow = node.type === 'subworkflow';
52
- const hasError = node.data?.status === 'failed';
53
-
54
- return (
55
- <ContextMenu>
56
- {children}
57
- <ContextMenuContent>
58
- <ContextMenuItem onClick={onEdit}>
59
- <Edit className="w-4 h-4 mr-2" />
60
- Edit Step
61
- <ContextMenuShortcut>E</ContextMenuShortcut>
62
- </ContextMenuItem>
63
-
64
- <ContextMenuItem onClick={onViewYaml}>
65
- <Code className="w-4 h-4 mr-2" />
66
- View YAML
67
- <ContextMenuShortcut>Y</ContextMenuShortcut>
68
- </ContextMenuItem>
69
-
70
- <ContextMenuItem onClick={onViewDocs}>
71
- <FileText className="w-4 h-4 mr-2" />
72
- View Documentation
73
- </ContextMenuItem>
74
-
75
- <ContextMenuSeparator />
76
-
77
- <ContextMenuItem onClick={onDuplicate}>
78
- <Copy className="w-4 h-4 mr-2" />
79
- Duplicate
80
- <ContextMenuShortcut>⌘D</ContextMenuShortcut>
81
- </ContextMenuItem>
82
-
83
- <ContextMenuSub>
84
- <ContextMenuSubTrigger>
85
- <Plus className="w-4 h-4 mr-2" />
86
- Add Step
87
- </ContextMenuSubTrigger>
88
- <ContextMenuSubContent>
89
- <ContextMenuItem onClick={onAddStepBefore}>
90
- Before this step
91
- </ContextMenuItem>
92
- <ContextMenuItem onClick={onAddStepAfter}>
93
- After this step
94
- </ContextMenuItem>
95
- </ContextMenuSubContent>
96
- </ContextMenuSub>
97
-
98
- {!isSubworkflow && (
99
- <ContextMenuItem onClick={onConvertToSubworkflow}>
100
- <FolderOpen className="w-4 h-4 mr-2" />
101
- Convert to Sub-workflow
102
- </ContextMenuItem>
103
- )}
104
-
105
- <ContextMenuSeparator />
106
-
107
- <ContextMenuItem onClick={onExecuteFrom}>
108
- <Play className="w-4 h-4 mr-2" />
109
- Execute from here
110
- </ContextMenuItem>
111
-
112
- {hasError && (
113
- <ContextMenuItem className="text-error">
114
- <AlertTriangle className="w-4 h-4 mr-2" />
115
- View Error Details
116
- </ContextMenuItem>
117
- )}
118
-
119
- <ContextMenuSeparator />
120
-
121
- <ContextMenuItem destructive onClick={onDelete}>
122
- <Trash2 className="w-4 h-4 mr-2" />
123
- Delete
124
- <ContextMenuShortcut>⌫</ContextMenuShortcut>
125
- </ContextMenuItem>
126
- </ContextMenuContent>
127
- </ContextMenu>
128
- );
129
- }
130
-
131
- // Canvas context menu (right-click on empty space)
132
- interface CanvasContextMenuProps {
133
- children: React.ReactNode;
134
- onAddStep: () => void;
135
- onAddSubworkflow: () => void;
136
- onPaste: () => void;
137
- onAutoLayout: () => void;
138
- onFitView: () => void;
139
- canPaste: boolean;
140
- }
141
-
142
- export function CanvasContextMenu({
143
- children,
144
- onAddStep,
145
- onAddSubworkflow,
146
- onPaste,
147
- onAutoLayout,
148
- onFitView,
149
- canPaste,
150
- }: CanvasContextMenuProps) {
151
- return (
152
- <ContextMenu>
153
- {children}
154
- <ContextMenuContent>
155
- <ContextMenuItem onClick={onAddStep}>
156
- <Plus className="w-4 h-4 mr-2" />
157
- Add Step
158
- <ContextMenuShortcut>N</ContextMenuShortcut>
159
- </ContextMenuItem>
160
-
161
- <ContextMenuItem onClick={onAddSubworkflow}>
162
- <FolderOpen className="w-4 h-4 mr-2" />
163
- Add Sub-workflow
164
- </ContextMenuItem>
165
-
166
- <ContextMenuSeparator />
167
-
168
- <ContextMenuItem onClick={onPaste} disabled={!canPaste}>
169
- <Copy className="w-4 h-4 mr-2" />
170
- Paste
171
- <ContextMenuShortcut>⌘V</ContextMenuShortcut>
172
- </ContextMenuItem>
173
-
174
- <ContextMenuSeparator />
175
-
176
- <ContextMenuItem onClick={onAutoLayout}>
177
- Auto-layout
178
- <ContextMenuShortcut>⌘L</ContextMenuShortcut>
179
- </ContextMenuItem>
180
-
181
- <ContextMenuItem onClick={onFitView}>
182
- Fit to View
183
- <ContextMenuShortcut>⌘0</ContextMenuShortcut>
184
- </ContextMenuItem>
185
- </ContextMenuContent>
186
- </ContextMenu>
187
- );
188
- }
@@ -1,111 +0,0 @@
1
- import { memo } from 'react';
2
- import { Handle, Position, type Node, type NodeProps } from '@xyflow/react';
3
- import { Flag, CheckCircle, XCircle, Clock } from 'lucide-react';
4
-
5
- export interface OutputNodeData extends Record<string, unknown> {
6
- id: string;
7
- name?: string;
8
- description?: string;
9
- variables?: string[];
10
- status?: 'pending' | 'completed' | 'failed';
11
- result?: unknown;
12
- }
13
-
14
- export type OutputNodeType = Node<OutputNodeData, 'output'>;
15
-
16
- function OutputNodeComponent({ data, selected }: NodeProps<OutputNodeType>) {
17
- const statusConfig = {
18
- pending: {
19
- icon: Clock,
20
- color: 'text-gray-400',
21
- borderColor: 'border-gray-500',
22
- bgColor: 'bg-gray-500/10',
23
- },
24
- completed: {
25
- icon: CheckCircle,
26
- color: 'text-success',
27
- borderColor: 'border-success',
28
- bgColor: 'bg-success/10',
29
- },
30
- failed: {
31
- icon: XCircle,
32
- color: 'text-error',
33
- borderColor: 'border-error',
34
- bgColor: 'bg-error/10',
35
- },
36
- };
37
-
38
- const status = data.status || 'pending';
39
- const config = statusConfig[status];
40
- const StatusIcon = config.icon;
41
-
42
- return (
43
- <div
44
- className={`min-w-[160px] rounded-lg border-2 ${config.borderColor} ${config.bgColor} ${
45
- selected ? 'ring-2 ring-primary ring-offset-2 ring-offset-canvas-bg' : ''
46
- } transition-all duration-200`}
47
- >
48
- {/* Input handle */}
49
- <Handle
50
- type="target"
51
- position={Position.Top}
52
- className="!w-3 !h-3 !bg-primary !border-2 !border-canvas-bg"
53
- />
54
-
55
- {/* Header */}
56
- <div className="px-3 py-2 flex items-center gap-2">
57
- <div className={`w-8 h-8 rounded-full ${config.bgColor} flex items-center justify-center`}>
58
- <Flag className={`w-4 h-4 ${config.color}`} />
59
- </div>
60
- <div className="flex-1 min-w-0">
61
- <div className="text-xs font-medium text-gray-400 uppercase tracking-wider">
62
- Output
63
- </div>
64
- <div className="text-sm font-medium text-white truncate">
65
- {data.name || 'Workflow End'}
66
- </div>
67
- </div>
68
- <StatusIcon className={`w-4 h-4 ${config.color}`} />
69
- </div>
70
-
71
- {/* Variables */}
72
- {data.variables && data.variables.length > 0 && (
73
- <div className="px-3 py-2 border-t border-white/10">
74
- <div className="text-xs text-gray-500 mb-1">Output Variables</div>
75
- <div className="flex flex-wrap gap-1">
76
- {data.variables.map((variable) => (
77
- <code
78
- key={variable}
79
- className="px-1.5 py-0.5 bg-white/5 text-primary text-xs rounded"
80
- >
81
- {variable}
82
- </code>
83
- ))}
84
- </div>
85
- </div>
86
- )}
87
-
88
- {/* Description */}
89
- {data.description && (
90
- <div className="px-3 py-2 border-t border-white/10">
91
- <div className="text-xs text-gray-400">{data.description}</div>
92
- </div>
93
- )}
94
-
95
- {/* Result preview */}
96
- {status === 'completed' && data.result !== undefined && (
97
- <div className="px-3 py-2 border-t border-white/10">
98
- <div className="text-xs text-gray-500 mb-1">Result</div>
99
- <pre className="text-xs text-success font-mono bg-black/20 rounded p-1.5 overflow-x-auto max-h-20">
100
- {typeof data.result === 'string'
101
- ? data.result.slice(0, 100)
102
- : JSON.stringify(data.result, null, 2).slice(0, 100)}
103
- {(typeof data.result === 'string' ? data.result : JSON.stringify(data.result)).length > 100 && '...'}
104
- </pre>
105
- </div>
106
- )}
107
- </div>
108
- );
109
- }
110
-
111
- export const OutputNode = memo(OutputNodeComponent);
@@ -1,106 +0,0 @@
1
- import { memo } from 'react';
2
- import { Handle, Position, type Node, type NodeProps } from '@xyflow/react';
3
- import { Play, CheckCircle, XCircle, Clock, AlertCircle } from 'lucide-react';
4
- import { getServiceIcon } from '../../utils/serviceIcons';
5
-
6
- export interface StepNodeData extends Record<string, unknown> {
7
- id: string;
8
- name?: string;
9
- action: string;
10
- status?: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
11
- retryCount?: number;
12
- error?: string;
13
- }
14
-
15
- export type StepNodeType = Node<StepNodeData, 'step'>;
16
-
17
- function StepNodeComponent({ data, selected }: NodeProps<StepNodeType>) {
18
- const serviceName = data.action?.split('.')[0] || 'unknown';
19
- const methodName = data.action?.split('.').slice(1).join('.') || data.action;
20
- const ServiceIcon = getServiceIcon(serviceName);
21
-
22
- const statusConfig: Record<
23
- NonNullable<StepNodeData['status']>,
24
- { icon: typeof Clock; color: string; bgColor: string; animate?: boolean }
25
- > = {
26
- pending: { icon: Clock, color: 'text-gray-400', bgColor: 'bg-gray-400/10' },
27
- running: {
28
- icon: Play,
29
- color: 'text-warning',
30
- bgColor: 'bg-warning/10',
31
- animate: true,
32
- },
33
- completed: {
34
- icon: CheckCircle,
35
- color: 'text-success',
36
- bgColor: 'bg-success/10',
37
- },
38
- failed: { icon: XCircle, color: 'text-error', bgColor: 'bg-error/10' },
39
- skipped: {
40
- icon: AlertCircle,
41
- color: 'text-gray-500',
42
- bgColor: 'bg-gray-500/10',
43
- },
44
- };
45
-
46
- const status = data.status || 'pending';
47
- const config = statusConfig[status];
48
- const StatusIcon = config.icon;
49
-
50
- return (
51
- <div
52
- className={`step-node p-0 ${selected ? 'selected' : ''} ${status === 'running' ? 'running' : ''} ${status === 'completed' ? 'completed' : ''} ${status === 'failed' ? 'failed' : ''}`}
53
- >
54
- {/* Input handle */}
55
- <Handle
56
- type="target"
57
- position={Position.Top}
58
- className="!w-3 !h-3 !bg-primary !border-2 !border-node-bg"
59
- />
60
-
61
- {/* Node header */}
62
- <div className="flex items-center gap-3 p-3 border-b border-node-border">
63
- <div className="w-8 h-8 rounded-lg bg-primary/10 flex items-center justify-center">
64
- <ServiceIcon className="w-5 h-5 text-primary" />
65
- </div>
66
- <div className="flex-1 min-w-0">
67
- <div className="text-sm font-medium text-white truncate">
68
- {data.name || data.id}
69
- </div>
70
- <div className="text-xs text-gray-400 truncate">{serviceName}</div>
71
- </div>
72
- <div
73
- className={`w-6 h-6 rounded-full ${config.bgColor} flex items-center justify-center`}
74
- >
75
- <StatusIcon
76
- className={`w-4 h-4 ${config.color} ${config.animate ? 'animate-pulse' : ''}`}
77
- />
78
- </div>
79
- </div>
80
-
81
- {/* Node body */}
82
- <div className="p-3">
83
- <div className="text-xs text-gray-300 font-mono truncate">
84
- {methodName}
85
- </div>
86
- {data.retryCount && data.retryCount > 0 && (
87
- <div className="mt-2 text-xs text-warning">
88
- Retry #{data.retryCount}
89
- </div>
90
- )}
91
- {data.error && (
92
- <div className="mt-2 text-xs text-error truncate">{data.error}</div>
93
- )}
94
- </div>
95
-
96
- {/* Output handle */}
97
- <Handle
98
- type="source"
99
- position={Position.Bottom}
100
- className="!w-3 !h-3 !bg-primary !border-2 !border-node-bg"
101
- />
102
- </div>
103
- );
104
- }
105
-
106
- export const StepNode = memo(StepNodeComponent);
@@ -1,141 +0,0 @@
1
- import { memo, useState, useCallback } from 'react';
2
- import { Handle, Position, type Node, type NodeProps } from '@xyflow/react';
3
- import {
4
- FolderOpen,
5
- ChevronDown,
6
- ChevronRight,
7
- ExternalLink,
8
- ArrowRight,
9
- } from 'lucide-react';
10
- import { useNavigationStore } from '../../stores/navigationStore';
11
- import { useWorkflowStore } from '../../stores/workflowStore';
12
-
13
- export interface SubWorkflowNodeData extends Record<string, unknown> {
14
- id: string;
15
- name?: string;
16
- workflowPath: string;
17
- stepCount?: number;
18
- status?: 'pending' | 'running' | 'completed' | 'failed';
19
- }
20
-
21
- export type SubWorkflowNodeType = Node<SubWorkflowNodeData, 'subworkflow'>;
22
-
23
- function SubWorkflowNodeComponent({
24
- data,
25
- selected,
26
- }: NodeProps<SubWorkflowNodeType>) {
27
- const [expanded, setExpanded] = useState(false);
28
- const { pushWorkflow, breadcrumbs, setRootWorkflow } = useNavigationStore();
29
- const { loadWorkflow, selectedWorkflow, currentWorkflow } = useWorkflowStore();
30
-
31
- // Handle drilling down into sub-workflow
32
- const handleDrillDown = useCallback(() => {
33
- // If this is the first navigation, set the current workflow as root
34
- if (breadcrumbs.length === 0 && selectedWorkflow && currentWorkflow) {
35
- setRootWorkflow({
36
- id: selectedWorkflow,
37
- name: currentWorkflow.metadata?.name || 'Main Workflow',
38
- path: selectedWorkflow,
39
- });
40
- }
41
-
42
- // Push the sub-workflow onto the navigation stack
43
- pushWorkflow({
44
- id: data.id,
45
- name: data.name || data.id,
46
- path: data.workflowPath,
47
- });
48
-
49
- // Load the sub-workflow
50
- loadWorkflow(data.workflowPath);
51
- }, [data, pushWorkflow, breadcrumbs, setRootWorkflow, selectedWorkflow, currentWorkflow, loadWorkflow]);
52
-
53
- const statusColors = {
54
- pending: 'border-node-border',
55
- running: 'border-warning',
56
- completed: 'border-success',
57
- failed: 'border-error',
58
- };
59
-
60
- const status = data.status || 'pending';
61
-
62
- return (
63
- <div
64
- className={`step-node p-0 min-w-[250px] ${selected ? 'selected' : ''} ${statusColors[status]}`}
65
- >
66
- {/* Input handle */}
67
- <Handle
68
- type="target"
69
- position={Position.Top}
70
- className="!w-3 !h-3 !bg-info !border-2 !border-node-bg"
71
- />
72
-
73
- {/* Node header */}
74
- <div className="flex items-center gap-3 p-3 border-b border-node-border bg-info/5">
75
- <button
76
- onClick={() => setExpanded(!expanded)}
77
- className="w-6 h-6 rounded flex items-center justify-center hover:bg-white/10 transition-colors"
78
- >
79
- {expanded ? (
80
- <ChevronDown className="w-4 h-4 text-info" />
81
- ) : (
82
- <ChevronRight className="w-4 h-4 text-info" />
83
- )}
84
- </button>
85
- <div className="w-8 h-8 rounded-lg bg-info/10 flex items-center justify-center">
86
- <FolderOpen className="w-5 h-5 text-info" />
87
- </div>
88
- <div className="flex-1 min-w-0">
89
- <div className="text-sm font-medium text-white truncate">
90
- {data.name || data.id}
91
- </div>
92
- <div className="text-xs text-gray-400">Sub-workflow</div>
93
- </div>
94
- <button
95
- onClick={handleDrillDown}
96
- className="w-6 h-6 rounded flex items-center justify-center hover:bg-info/20 transition-colors"
97
- title="Drill into sub-workflow"
98
- >
99
- <ArrowRight className="w-4 h-4 text-info" />
100
- </button>
101
- </div>
102
-
103
- {/* Node body */}
104
- <div className="p-3">
105
- <div className="text-xs text-gray-400 font-mono truncate">
106
- {data.workflowPath}
107
- </div>
108
- {data.stepCount !== undefined && (
109
- <div className="mt-2 flex items-center gap-2">
110
- <span className="text-xs px-2 py-0.5 rounded-full bg-info/10 text-info">
111
- {data.stepCount} steps
112
- </span>
113
- </div>
114
- )}
115
- </div>
116
-
117
- {/* Expanded content */}
118
- {expanded && (
119
- <div className="border-t border-node-border p-3 bg-black/20">
120
- <button
121
- onClick={handleDrillDown}
122
- className="w-full flex items-center justify-center gap-2 px-3 py-2 bg-info/10 hover:bg-info/20 rounded text-sm text-info transition-colors"
123
- >
124
- <FolderOpen className="w-4 h-4" />
125
- Open Sub-workflow
126
- <ArrowRight className="w-4 h-4" />
127
- </button>
128
- </div>
129
- )}
130
-
131
- {/* Output handle */}
132
- <Handle
133
- type="source"
134
- position={Position.Bottom}
135
- className="!w-3 !h-3 !bg-info !border-2 !border-node-bg"
136
- />
137
- </div>
138
- );
139
- }
140
-
141
- export const SubWorkflowNode = memo(SubWorkflowNodeComponent);