@marktoflow/gui 2.0.0-alpha.1

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 (165) hide show
  1. package/.turbo/turbo-build.log +26 -0
  2. package/.turbo/turbo-test.log +22 -0
  3. package/README.md +179 -0
  4. package/dist/client/assets/index-DwTI8opO.js +608 -0
  5. package/dist/client/assets/index-DwTI8opO.js.map +1 -0
  6. package/dist/client/assets/index-RoEdL6gO.css +1 -0
  7. package/dist/client/index.html +20 -0
  8. package/dist/client/vite.svg +9 -0
  9. package/dist/server/index.d.ts +3 -0
  10. package/dist/server/index.d.ts.map +1 -0
  11. package/dist/server/index.js +56 -0
  12. package/dist/server/index.js.map +1 -0
  13. package/dist/server/routes/ai.js +50 -0
  14. package/dist/server/routes/ai.js.map +1 -0
  15. package/dist/server/routes/execute.js +62 -0
  16. package/dist/server/routes/execute.js.map +1 -0
  17. package/dist/server/routes/workflows.js +99 -0
  18. package/dist/server/routes/workflows.js.map +1 -0
  19. package/dist/server/server/index.js +95 -0
  20. package/dist/server/server/index.js.map +1 -0
  21. package/dist/server/server/routes/ai.js +87 -0
  22. package/dist/server/server/routes/ai.js.map +1 -0
  23. package/dist/server/server/routes/execute.js +63 -0
  24. package/dist/server/server/routes/execute.js.map +1 -0
  25. package/dist/server/server/routes/tools.js +518 -0
  26. package/dist/server/server/routes/tools.js.map +1 -0
  27. package/dist/server/server/routes/workflows.js +99 -0
  28. package/dist/server/server/routes/workflows.js.map +1 -0
  29. package/dist/server/server/services/AIService.js +69 -0
  30. package/dist/server/server/services/AIService.js.map +1 -0
  31. package/dist/server/server/services/FileWatcher.js +60 -0
  32. package/dist/server/server/services/FileWatcher.js.map +1 -0
  33. package/dist/server/server/services/WorkflowService.js +363 -0
  34. package/dist/server/server/services/WorkflowService.js.map +1 -0
  35. package/dist/server/server/services/agents/claude-code-provider.js +250 -0
  36. package/dist/server/server/services/agents/claude-code-provider.js.map +1 -0
  37. package/dist/server/server/services/agents/claude-provider.js +204 -0
  38. package/dist/server/server/services/agents/claude-provider.js.map +1 -0
  39. package/dist/server/server/services/agents/copilot-provider.js +227 -0
  40. package/dist/server/server/services/agents/copilot-provider.js.map +1 -0
  41. package/dist/server/server/services/agents/demo-provider.js +167 -0
  42. package/dist/server/server/services/agents/demo-provider.js.map +1 -0
  43. package/dist/server/server/services/agents/index.js +31 -0
  44. package/dist/server/server/services/agents/index.js.map +1 -0
  45. package/dist/server/server/services/agents/ollama-provider.js +220 -0
  46. package/dist/server/server/services/agents/ollama-provider.js.map +1 -0
  47. package/dist/server/server/services/agents/prompts.js +436 -0
  48. package/dist/server/server/services/agents/prompts.js.map +1 -0
  49. package/dist/server/server/services/agents/registry.js +242 -0
  50. package/dist/server/server/services/agents/registry.js.map +1 -0
  51. package/dist/server/server/services/agents/types.js +6 -0
  52. package/dist/server/server/services/agents/types.js.map +1 -0
  53. package/dist/server/server/websocket/index.js +85 -0
  54. package/dist/server/server/websocket/index.js.map +1 -0
  55. package/dist/server/services/AIService.d.ts +30 -0
  56. package/dist/server/services/AIService.d.ts.map +1 -0
  57. package/dist/server/services/AIService.js +216 -0
  58. package/dist/server/services/AIService.js.map +1 -0
  59. package/dist/server/services/FileWatcher.d.ts +10 -0
  60. package/dist/server/services/FileWatcher.d.ts.map +1 -0
  61. package/dist/server/services/FileWatcher.js +62 -0
  62. package/dist/server/services/FileWatcher.js.map +1 -0
  63. package/dist/server/services/WorkflowService.d.ts +54 -0
  64. package/dist/server/services/WorkflowService.d.ts.map +1 -0
  65. package/dist/server/services/WorkflowService.js +323 -0
  66. package/dist/server/services/WorkflowService.js.map +1 -0
  67. package/dist/server/shared/constants.js +175 -0
  68. package/dist/server/shared/constants.js.map +1 -0
  69. package/dist/server/shared/types.js +3 -0
  70. package/dist/server/shared/types.js.map +1 -0
  71. package/dist/server/websocket/index.d.ts +10 -0
  72. package/dist/server/websocket/index.d.ts.map +1 -0
  73. package/dist/server/websocket/index.js +85 -0
  74. package/dist/server/websocket/index.js.map +1 -0
  75. package/index.html +19 -0
  76. package/package.json +96 -0
  77. package/playwright.config.ts +27 -0
  78. package/postcss.config.js +6 -0
  79. package/public/vite.svg +9 -0
  80. package/src/client/App.tsx +520 -0
  81. package/src/client/components/Canvas/Canvas.tsx +405 -0
  82. package/src/client/components/Canvas/ExecutionOverlay.tsx +847 -0
  83. package/src/client/components/Canvas/NodeContextMenu.tsx +188 -0
  84. package/src/client/components/Canvas/OutputNode.tsx +111 -0
  85. package/src/client/components/Canvas/StepNode.tsx +106 -0
  86. package/src/client/components/Canvas/SubWorkflowNode.tsx +141 -0
  87. package/src/client/components/Canvas/Toolbar.tsx +189 -0
  88. package/src/client/components/Canvas/TriggerNode.tsx +128 -0
  89. package/src/client/components/Editor/InputsEditor.tsx +458 -0
  90. package/src/client/components/Editor/NewStepWizard.tsx +344 -0
  91. package/src/client/components/Editor/StepEditor.tsx +532 -0
  92. package/src/client/components/Editor/YamlEditor.tsx +160 -0
  93. package/src/client/components/Panels/PropertiesPanel.tsx +589 -0
  94. package/src/client/components/Prompt/ChangePreview.tsx +281 -0
  95. package/src/client/components/Prompt/PromptHistoryPanel.tsx +209 -0
  96. package/src/client/components/Prompt/PromptInput.tsx +108 -0
  97. package/src/client/components/Sidebar/Sidebar.tsx +343 -0
  98. package/src/client/components/common/Breadcrumb.tsx +40 -0
  99. package/src/client/components/common/Button.tsx +68 -0
  100. package/src/client/components/common/ContextMenu.tsx +202 -0
  101. package/src/client/components/common/KeyboardShortcuts.tsx +143 -0
  102. package/src/client/components/common/Modal.tsx +93 -0
  103. package/src/client/components/common/Tabs.tsx +57 -0
  104. package/src/client/components/common/ThemeToggle.tsx +63 -0
  105. package/src/client/components/index.ts +32 -0
  106. package/src/client/hooks/index.ts +4 -0
  107. package/src/client/hooks/useAIPrompt.ts +108 -0
  108. package/src/client/hooks/useCanvas.ts +247 -0
  109. package/src/client/hooks/useWebSocket.ts +164 -0
  110. package/src/client/hooks/useWorkflow.ts +138 -0
  111. package/src/client/main.tsx +10 -0
  112. package/src/client/stores/canvasStore.ts +348 -0
  113. package/src/client/stores/editorStore.ts +133 -0
  114. package/src/client/stores/executionStore.ts +440 -0
  115. package/src/client/stores/index.ts +4 -0
  116. package/src/client/stores/layoutStore.ts +103 -0
  117. package/src/client/stores/navigationStore.ts +49 -0
  118. package/src/client/stores/promptStore.ts +113 -0
  119. package/src/client/stores/themeStore.ts +75 -0
  120. package/src/client/stores/workflowStore.ts +177 -0
  121. package/src/client/styles/globals.css +346 -0
  122. package/src/client/utils/cn.ts +9 -0
  123. package/src/client/utils/index.ts +4 -0
  124. package/src/client/utils/serviceIcons.tsx +64 -0
  125. package/src/client/utils/stepValidation.ts +155 -0
  126. package/src/client/utils/workflowToGraph.ts +299 -0
  127. package/src/server/index.ts +114 -0
  128. package/src/server/routes/ai.ts +91 -0
  129. package/src/server/routes/execute.ts +71 -0
  130. package/src/server/routes/tools.ts +564 -0
  131. package/src/server/routes/workflows.ts +106 -0
  132. package/src/server/services/AIService.ts +105 -0
  133. package/src/server/services/FileWatcher.ts +69 -0
  134. package/src/server/services/WorkflowService.ts +441 -0
  135. package/src/server/services/agents/claude-code-provider.ts +320 -0
  136. package/src/server/services/agents/claude-provider.ts +248 -0
  137. package/src/server/services/agents/copilot-provider.ts +311 -0
  138. package/src/server/services/agents/demo-provider.ts +184 -0
  139. package/src/server/services/agents/index.ts +31 -0
  140. package/src/server/services/agents/ollama-provider.ts +267 -0
  141. package/src/server/services/agents/prompts.ts +482 -0
  142. package/src/server/services/agents/registry.ts +289 -0
  143. package/src/server/services/agents/types.ts +146 -0
  144. package/src/server/websocket/index.ts +104 -0
  145. package/src/shared/constants.ts +180 -0
  146. package/src/shared/types.ts +179 -0
  147. package/tailwind.config.ts +73 -0
  148. package/tests/e2e/app.spec.ts +90 -0
  149. package/tests/e2e/canvas.spec.ts +128 -0
  150. package/tests/e2e/workflow.spec.ts +185 -0
  151. package/tests/integration/api.test.ts +250 -0
  152. package/tests/integration/testApp.ts +31 -0
  153. package/tests/setup.ts +37 -0
  154. package/tests/unit/canvasStore.test.ts +502 -0
  155. package/tests/unit/components.test.tsx +151 -0
  156. package/tests/unit/executionStore.test.ts +527 -0
  157. package/tests/unit/layoutStore.test.ts +194 -0
  158. package/tests/unit/navigationStore.test.ts +152 -0
  159. package/tests/unit/stepValidation.test.ts +226 -0
  160. package/tests/unit/themeStore.test.ts +141 -0
  161. package/tests/unit/workflowToGraph.test.ts +289 -0
  162. package/tsconfig.json +29 -0
  163. package/tsconfig.server.json +28 -0
  164. package/vite.config.ts +31 -0
  165. package/vitest.config.ts +26 -0
@@ -0,0 +1,189 @@
1
+ import {
2
+ Plus,
3
+ Play,
4
+ Pause,
5
+ Layout,
6
+ ZoomIn,
7
+ ZoomOut,
8
+ Maximize,
9
+ Save,
10
+ Undo,
11
+ Redo,
12
+ Copy,
13
+ Trash2,
14
+ } from 'lucide-react';
15
+ import { useCanvas } from '../../hooks/useCanvas';
16
+ import { useEditorStore } from '../../stores/editorStore';
17
+ import { useReactFlow } from '@xyflow/react';
18
+
19
+ interface ToolbarProps {
20
+ onAddStep: () => void;
21
+ onExecute?: () => void;
22
+ onSave?: () => void;
23
+ isExecuting?: boolean;
24
+ }
25
+
26
+ export function Toolbar({
27
+ onAddStep,
28
+ onExecute,
29
+ onSave,
30
+ isExecuting = false,
31
+ }: ToolbarProps) {
32
+ const { autoLayout, fitView, selectedNodes, deleteSelected, duplicateSelected } =
33
+ useCanvas();
34
+ const { undo, redo, undoStack, redoStack } = useEditorStore();
35
+ const { zoomIn, zoomOut } = useReactFlow();
36
+
37
+ const canUndo = undoStack.length > 0;
38
+ const canRedo = redoStack.length > 0;
39
+ const hasSelection = selectedNodes.length > 0;
40
+
41
+ return (
42
+ <div className="absolute top-4 left-1/2 -translate-x-1/2 z-10 flex items-center gap-1 px-2 py-1.5 bg-panel-bg/95 backdrop-blur border border-node-border rounded-lg shadow-lg">
43
+ {/* Add Step */}
44
+ <ToolbarButton
45
+ icon={<Plus className="w-4 h-4" />}
46
+ label="Add Step"
47
+ onClick={onAddStep}
48
+ shortcut="N"
49
+ />
50
+
51
+ <ToolbarDivider />
52
+
53
+ {/* Undo/Redo */}
54
+ <ToolbarButton
55
+ icon={<Undo className="w-4 h-4" />}
56
+ label="Undo"
57
+ onClick={() => undo()}
58
+ disabled={!canUndo}
59
+ shortcut="⌘Z"
60
+ />
61
+ <ToolbarButton
62
+ icon={<Redo className="w-4 h-4" />}
63
+ label="Redo"
64
+ onClick={() => redo()}
65
+ disabled={!canRedo}
66
+ shortcut="⌘⇧Z"
67
+ />
68
+
69
+ <ToolbarDivider />
70
+
71
+ {/* Selection actions */}
72
+ <ToolbarButton
73
+ icon={<Copy className="w-4 h-4" />}
74
+ label="Duplicate"
75
+ onClick={duplicateSelected}
76
+ disabled={!hasSelection}
77
+ shortcut="⌘D"
78
+ />
79
+ <ToolbarButton
80
+ icon={<Trash2 className="w-4 h-4" />}
81
+ label="Delete"
82
+ onClick={deleteSelected}
83
+ disabled={!hasSelection}
84
+ shortcut="⌫"
85
+ />
86
+
87
+ <ToolbarDivider />
88
+
89
+ {/* Layout & Zoom */}
90
+ <ToolbarButton
91
+ icon={<Layout className="w-4 h-4" />}
92
+ label="Auto Layout"
93
+ onClick={autoLayout}
94
+ shortcut="⌘L"
95
+ />
96
+ <ToolbarButton
97
+ icon={<ZoomIn className="w-4 h-4" />}
98
+ label="Zoom In"
99
+ onClick={() => zoomIn()}
100
+ shortcut="⌘+"
101
+ />
102
+ <ToolbarButton
103
+ icon={<ZoomOut className="w-4 h-4" />}
104
+ label="Zoom Out"
105
+ onClick={() => zoomOut()}
106
+ shortcut="⌘-"
107
+ />
108
+ <ToolbarButton
109
+ icon={<Maximize className="w-4 h-4" />}
110
+ label="Fit View"
111
+ onClick={fitView}
112
+ shortcut="⌘0"
113
+ />
114
+
115
+ <ToolbarDivider />
116
+
117
+ {/* Execute */}
118
+ {onExecute && (
119
+ <ToolbarButton
120
+ icon={
121
+ isExecuting ? (
122
+ <Pause className="w-4 h-4" />
123
+ ) : (
124
+ <Play className="w-4 h-4" />
125
+ )
126
+ }
127
+ label={isExecuting ? 'Stop' : 'Execute'}
128
+ onClick={onExecute}
129
+ variant={isExecuting ? 'destructive' : 'primary'}
130
+ shortcut="⌘⏎"
131
+ />
132
+ )}
133
+
134
+ {/* Save */}
135
+ {onSave && (
136
+ <ToolbarButton
137
+ icon={<Save className="w-4 h-4" />}
138
+ label="Save"
139
+ onClick={onSave}
140
+ shortcut="⌘S"
141
+ />
142
+ )}
143
+ </div>
144
+ );
145
+ }
146
+
147
+ interface ToolbarButtonProps {
148
+ icon: React.ReactNode;
149
+ label: string;
150
+ onClick: () => void;
151
+ disabled?: boolean;
152
+ shortcut?: string;
153
+ variant?: 'default' | 'primary' | 'destructive';
154
+ }
155
+
156
+ function ToolbarButton({
157
+ icon,
158
+ label,
159
+ onClick,
160
+ disabled,
161
+ shortcut,
162
+ variant = 'default',
163
+ }: ToolbarButtonProps) {
164
+ const variantClasses = {
165
+ default: 'text-gray-300 hover:text-white hover:bg-white/10',
166
+ primary: 'text-primary hover:text-primary-light hover:bg-primary/10',
167
+ destructive: 'text-error hover:text-error hover:bg-error/10',
168
+ };
169
+
170
+ return (
171
+ <button
172
+ onClick={onClick}
173
+ disabled={disabled}
174
+ className={`relative group p-2 rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed ${variantClasses[variant]}`}
175
+ title={`${label}${shortcut ? ` (${shortcut})` : ''}`}
176
+ >
177
+ {icon}
178
+ {/* Tooltip */}
179
+ <div className="absolute top-full left-1/2 -translate-x-1/2 mt-2 px-2 py-1 bg-black/90 rounded text-xs text-white whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none">
180
+ {label}
181
+ {shortcut && <span className="ml-2 text-gray-400">{shortcut}</span>}
182
+ </div>
183
+ </button>
184
+ );
185
+ }
186
+
187
+ function ToolbarDivider() {
188
+ return <div className="w-px h-6 bg-node-border mx-1" />;
189
+ }
@@ -0,0 +1,128 @@
1
+ import { memo } from 'react';
2
+ import { Handle, Position, type Node, type NodeProps } from '@xyflow/react';
3
+ import { Webhook, FolderOpen, Play, Zap, Calendar } from 'lucide-react';
4
+
5
+ export interface TriggerNodeData extends Record<string, unknown> {
6
+ id: string;
7
+ name?: string;
8
+ type: 'manual' | 'schedule' | 'webhook' | 'file' | 'event';
9
+ // Schedule trigger
10
+ cron?: string;
11
+ // Webhook trigger
12
+ path?: string;
13
+ method?: string;
14
+ // File watcher trigger
15
+ pattern?: string;
16
+ // Event trigger
17
+ events?: string[];
18
+ // Status
19
+ active?: boolean;
20
+ lastTriggered?: string;
21
+ }
22
+
23
+ export type TriggerNodeType = Node<TriggerNodeData, 'trigger'>;
24
+
25
+ const triggerConfig = {
26
+ manual: {
27
+ icon: Play,
28
+ color: 'text-primary',
29
+ bgColor: 'bg-primary/10',
30
+ borderColor: 'border-primary',
31
+ label: 'Manual Trigger',
32
+ },
33
+ schedule: {
34
+ icon: Calendar,
35
+ color: 'text-info',
36
+ bgColor: 'bg-info/10',
37
+ borderColor: 'border-info',
38
+ label: 'Schedule',
39
+ },
40
+ webhook: {
41
+ icon: Webhook,
42
+ color: 'text-success',
43
+ bgColor: 'bg-success/10',
44
+ borderColor: 'border-success',
45
+ label: 'Webhook',
46
+ },
47
+ file: {
48
+ icon: FolderOpen,
49
+ color: 'text-warning',
50
+ bgColor: 'bg-warning/10',
51
+ borderColor: 'border-warning',
52
+ label: 'File Watcher',
53
+ },
54
+ event: {
55
+ icon: Zap,
56
+ color: 'text-purple-400',
57
+ bgColor: 'bg-purple-400/10',
58
+ borderColor: 'border-purple-400',
59
+ label: 'Event',
60
+ },
61
+ };
62
+
63
+ function TriggerNodeComponent({ data, selected }: NodeProps<TriggerNodeType>) {
64
+ const config = triggerConfig[data.type] || triggerConfig.manual;
65
+ const Icon = config.icon;
66
+
67
+ const getSubtitle = () => {
68
+ switch (data.type) {
69
+ case 'schedule':
70
+ return data.cron || 'No schedule set';
71
+ case 'webhook':
72
+ return `${data.method || 'POST'} ${data.path || '/webhook'}`;
73
+ case 'file':
74
+ return data.pattern || '**/*';
75
+ case 'event':
76
+ return data.events?.join(', ') || 'No events';
77
+ default:
78
+ return 'Click to run';
79
+ }
80
+ };
81
+
82
+ return (
83
+ <div
84
+ className={`min-w-[180px] rounded-lg border-2 ${config.borderColor} ${config.bgColor} ${
85
+ selected ? 'ring-2 ring-primary ring-offset-2 ring-offset-canvas-bg' : ''
86
+ } transition-all duration-200`}
87
+ >
88
+ {/* Header */}
89
+ <div className="px-3 py-2 flex items-center gap-2">
90
+ <div className={`w-8 h-8 rounded-full ${config.bgColor} flex items-center justify-center`}>
91
+ <Icon className={`w-4 h-4 ${config.color}`} />
92
+ </div>
93
+ <div className="flex-1 min-w-0">
94
+ <div className="text-xs font-medium text-gray-400 uppercase tracking-wider">
95
+ {config.label}
96
+ </div>
97
+ <div className="text-sm font-medium text-white truncate">
98
+ {data.name || 'Trigger'}
99
+ </div>
100
+ </div>
101
+ {data.active !== false && (
102
+ <div className="w-2 h-2 rounded-full bg-success animate-pulse" title="Active" />
103
+ )}
104
+ </div>
105
+
106
+ {/* Details */}
107
+ <div className="px-3 py-2 border-t border-white/10">
108
+ <div className="text-xs text-gray-400 font-mono truncate" title={getSubtitle()}>
109
+ {getSubtitle()}
110
+ </div>
111
+ {data.lastTriggered && (
112
+ <div className="text-xs text-gray-500 mt-1">
113
+ Last: {new Date(data.lastTriggered).toLocaleString()}
114
+ </div>
115
+ )}
116
+ </div>
117
+
118
+ {/* Output handle */}
119
+ <Handle
120
+ type="source"
121
+ position={Position.Bottom}
122
+ className="!w-3 !h-3 !bg-primary !border-2 !border-canvas-bg"
123
+ />
124
+ </div>
125
+ );
126
+ }
127
+
128
+ export const TriggerNode = memo(TriggerNodeComponent);