@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,267 @@
1
+ /**
2
+ * Ollama AI agent provider
3
+ * Uses local Ollama instance for AI capabilities
4
+ */
5
+
6
+ import { stringify as yamlStringify, parse as yamlParse } from 'yaml';
7
+ import type {
8
+ AgentProvider,
9
+ AgentCapabilities,
10
+ AgentConfig,
11
+ PromptResult,
12
+ Workflow,
13
+ } from './types.js';
14
+
15
+ const SYSTEM_PROMPT = `You are an expert workflow automation assistant. Help users modify their workflows.
16
+
17
+ When modifying workflows:
18
+ - Each step has: id, name, action, inputs, output_variable
19
+ - Actions use format: service.method (e.g., slack.chat.postMessage)
20
+ - Template variables use: {{ variable_name }} syntax
21
+
22
+ Respond with:
23
+ 1. A brief explanation of changes
24
+ 2. The complete modified workflow in YAML format between \`\`\`yaml and \`\`\``;
25
+
26
+ export class OllamaProvider implements AgentProvider {
27
+ readonly id = 'ollama';
28
+ readonly name = 'Ollama (Local)';
29
+ readonly capabilities: AgentCapabilities = {
30
+ streaming: true,
31
+ toolUse: false,
32
+ codeExecution: false,
33
+ systemPrompts: true,
34
+ models: [
35
+ 'llama3.2',
36
+ 'llama3.1',
37
+ 'codellama',
38
+ 'mistral',
39
+ 'mixtral',
40
+ 'phi3',
41
+ 'gemma2',
42
+ ],
43
+ };
44
+
45
+ private baseUrl: string = 'http://localhost:11434';
46
+ private model: string = 'llama3.2';
47
+ private ready: boolean = false;
48
+ private error: string | undefined;
49
+
50
+ async initialize(config: AgentConfig): Promise<void> {
51
+ try {
52
+ if (config.baseUrl) {
53
+ this.baseUrl = config.baseUrl;
54
+ }
55
+ if (config.model) {
56
+ this.model = config.model;
57
+ }
58
+
59
+ // Check if Ollama is available
60
+ const response = await fetch(`${this.baseUrl}/api/tags`, {
61
+ method: 'GET',
62
+ signal: AbortSignal.timeout(5000),
63
+ });
64
+
65
+ if (response.ok) {
66
+ this.ready = true;
67
+ this.error = undefined;
68
+ } else {
69
+ this.ready = false;
70
+ this.error = 'Ollama server returned an error';
71
+ }
72
+ } catch (err) {
73
+ this.ready = false;
74
+ this.error = `Cannot connect to Ollama at ${this.baseUrl}. Is Ollama running?`;
75
+ }
76
+ }
77
+
78
+ isReady(): boolean {
79
+ return this.ready;
80
+ }
81
+
82
+ getStatus(): { ready: boolean; model?: string; error?: string } {
83
+ return {
84
+ ready: this.ready,
85
+ model: this.model,
86
+ error: this.error,
87
+ };
88
+ }
89
+
90
+ async processPrompt(prompt: string, workflow: Workflow): Promise<PromptResult> {
91
+ if (!this.ready) {
92
+ return {
93
+ explanation: 'Ollama is not available. Please ensure Ollama is running.',
94
+ error: this.error,
95
+ };
96
+ }
97
+
98
+ try {
99
+ const workflowYaml = yamlStringify(workflow, { indent: 2, lineWidth: 0 });
100
+
101
+ const response = await fetch(`${this.baseUrl}/api/generate`, {
102
+ method: 'POST',
103
+ headers: { 'Content-Type': 'application/json' },
104
+ body: JSON.stringify({
105
+ model: this.model,
106
+ prompt: `${SYSTEM_PROMPT}\n\nCurrent workflow:\n\`\`\`yaml\n${workflowYaml}\n\`\`\`\n\nUser request: ${prompt}`,
107
+ stream: false,
108
+ }),
109
+ });
110
+
111
+ if (!response.ok) {
112
+ throw new Error(`Ollama API error: ${response.status}`);
113
+ }
114
+
115
+ const data = (await response.json()) as { response: string };
116
+ return this.parseAIResponse(data.response, workflow);
117
+ } catch (err) {
118
+ return {
119
+ explanation: '',
120
+ error: err instanceof Error ? err.message : 'Unknown error',
121
+ };
122
+ }
123
+ }
124
+
125
+ async getSuggestions(workflow: Workflow, selectedStepId?: string): Promise<string[]> {
126
+ const suggestions: string[] = [];
127
+
128
+ if (!workflow || !workflow.steps) {
129
+ return [
130
+ 'Add your first step',
131
+ 'Create a simple workflow',
132
+ 'Add an HTTP request',
133
+ ];
134
+ }
135
+
136
+ suggestions.push(
137
+ 'Add error handling',
138
+ 'Add a notification step',
139
+ 'Simplify the workflow'
140
+ );
141
+
142
+ if (selectedStepId) {
143
+ const step = workflow.steps.find((s) => s.id === selectedStepId);
144
+ if (step) {
145
+ suggestions.push(
146
+ `Improve "${step.name || step.id}"`,
147
+ `Add validation to "${step.name || step.id}"`
148
+ );
149
+ }
150
+ }
151
+
152
+ return suggestions.slice(0, 5);
153
+ }
154
+
155
+ async streamPrompt(
156
+ prompt: string,
157
+ workflow: Workflow,
158
+ onChunk: (chunk: string) => void
159
+ ): Promise<PromptResult> {
160
+ if (!this.ready) {
161
+ return this.processPrompt(prompt, workflow);
162
+ }
163
+
164
+ const workflowYaml = yamlStringify(workflow, { indent: 2, lineWidth: 0 });
165
+ let fullResponse = '';
166
+
167
+ try {
168
+ const response = await fetch(`${this.baseUrl}/api/generate`, {
169
+ method: 'POST',
170
+ headers: { 'Content-Type': 'application/json' },
171
+ body: JSON.stringify({
172
+ model: this.model,
173
+ prompt: `${SYSTEM_PROMPT}\n\nCurrent workflow:\n\`\`\`yaml\n${workflowYaml}\n\`\`\`\n\nUser request: ${prompt}`,
174
+ stream: true,
175
+ }),
176
+ });
177
+
178
+ if (!response.ok || !response.body) {
179
+ throw new Error(`Ollama API error: ${response.status}`);
180
+ }
181
+
182
+ const reader = response.body.getReader();
183
+ const decoder = new TextDecoder();
184
+
185
+ while (true) {
186
+ const { done, value } = await reader.read();
187
+ if (done) break;
188
+
189
+ const chunk = decoder.decode(value);
190
+ const lines = chunk.split('\n').filter(Boolean);
191
+
192
+ for (const line of lines) {
193
+ try {
194
+ const data = JSON.parse(line);
195
+ if (data.response) {
196
+ fullResponse += data.response;
197
+ onChunk(data.response);
198
+ }
199
+ } catch {
200
+ // Skip invalid JSON
201
+ }
202
+ }
203
+ }
204
+
205
+ return this.parseAIResponse(fullResponse, workflow);
206
+ } catch (err) {
207
+ return {
208
+ explanation: '',
209
+ error: err instanceof Error ? err.message : 'Unknown error',
210
+ };
211
+ }
212
+ }
213
+
214
+ private parseAIResponse(responseText: string, originalWorkflow: Workflow): PromptResult {
215
+ const yamlMatch = responseText.match(/```yaml\n([\s\S]*?)\n```/);
216
+ let modifiedWorkflow: Workflow | undefined;
217
+ let explanation = responseText;
218
+
219
+ if (yamlMatch) {
220
+ try {
221
+ const parsedYaml = yamlParse(yamlMatch[1]);
222
+ if (parsedYaml && (parsedYaml.steps || parsedYaml.metadata)) {
223
+ modifiedWorkflow = parsedYaml as Workflow;
224
+ const explanationMatch = responseText.match(/^([\s\S]*?)```yaml/);
225
+ if (explanationMatch) {
226
+ explanation = explanationMatch[1].trim();
227
+ }
228
+ }
229
+ } catch {
230
+ // Failed to parse YAML
231
+ }
232
+ }
233
+
234
+ let diff: string | undefined;
235
+ if (modifiedWorkflow) {
236
+ diff = this.generateDiff(originalWorkflow, modifiedWorkflow);
237
+ }
238
+
239
+ return { explanation, workflow: modifiedWorkflow, diff };
240
+ }
241
+
242
+ private generateDiff(original: Workflow, modified: Workflow): string {
243
+ const originalStepIds = new Set(original.steps?.map((s) => s.id) || []);
244
+ const modifiedStepIds = new Set(modified.steps?.map((s) => s.id) || []);
245
+
246
+ const added = modified.steps?.filter((s) => !originalStepIds.has(s.id)) || [];
247
+ const removed = original.steps?.filter((s) => !modifiedStepIds.has(s.id)) || [];
248
+
249
+ let diff = '';
250
+ if (added.length > 0) {
251
+ diff += `+ Added ${added.length} step(s)\n`;
252
+ }
253
+ if (removed.length > 0) {
254
+ diff += `- Removed ${removed.length} step(s)\n`;
255
+ }
256
+
257
+ return diff || 'No structural changes';
258
+ }
259
+ }
260
+
261
+ export function createOllamaProvider(config?: AgentConfig): OllamaProvider {
262
+ const provider = new OllamaProvider();
263
+ if (config) {
264
+ provider.initialize(config);
265
+ }
266
+ return provider;
267
+ }