@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.
- package/.turbo/turbo-build.log +26 -0
- package/.turbo/turbo-test.log +22 -0
- package/README.md +179 -0
- package/dist/client/assets/index-DwTI8opO.js +608 -0
- package/dist/client/assets/index-DwTI8opO.js.map +1 -0
- package/dist/client/assets/index-RoEdL6gO.css +1 -0
- package/dist/client/index.html +20 -0
- package/dist/client/vite.svg +9 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +56 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/ai.js +50 -0
- package/dist/server/routes/ai.js.map +1 -0
- package/dist/server/routes/execute.js +62 -0
- package/dist/server/routes/execute.js.map +1 -0
- package/dist/server/routes/workflows.js +99 -0
- package/dist/server/routes/workflows.js.map +1 -0
- package/dist/server/server/index.js +95 -0
- package/dist/server/server/index.js.map +1 -0
- package/dist/server/server/routes/ai.js +87 -0
- package/dist/server/server/routes/ai.js.map +1 -0
- package/dist/server/server/routes/execute.js +63 -0
- package/dist/server/server/routes/execute.js.map +1 -0
- package/dist/server/server/routes/tools.js +518 -0
- package/dist/server/server/routes/tools.js.map +1 -0
- package/dist/server/server/routes/workflows.js +99 -0
- package/dist/server/server/routes/workflows.js.map +1 -0
- package/dist/server/server/services/AIService.js +69 -0
- package/dist/server/server/services/AIService.js.map +1 -0
- package/dist/server/server/services/FileWatcher.js +60 -0
- package/dist/server/server/services/FileWatcher.js.map +1 -0
- package/dist/server/server/services/WorkflowService.js +363 -0
- package/dist/server/server/services/WorkflowService.js.map +1 -0
- package/dist/server/server/services/agents/claude-code-provider.js +250 -0
- package/dist/server/server/services/agents/claude-code-provider.js.map +1 -0
- package/dist/server/server/services/agents/claude-provider.js +204 -0
- package/dist/server/server/services/agents/claude-provider.js.map +1 -0
- package/dist/server/server/services/agents/copilot-provider.js +227 -0
- package/dist/server/server/services/agents/copilot-provider.js.map +1 -0
- package/dist/server/server/services/agents/demo-provider.js +167 -0
- package/dist/server/server/services/agents/demo-provider.js.map +1 -0
- package/dist/server/server/services/agents/index.js +31 -0
- package/dist/server/server/services/agents/index.js.map +1 -0
- package/dist/server/server/services/agents/ollama-provider.js +220 -0
- package/dist/server/server/services/agents/ollama-provider.js.map +1 -0
- package/dist/server/server/services/agents/prompts.js +436 -0
- package/dist/server/server/services/agents/prompts.js.map +1 -0
- package/dist/server/server/services/agents/registry.js +242 -0
- package/dist/server/server/services/agents/registry.js.map +1 -0
- package/dist/server/server/services/agents/types.js +6 -0
- package/dist/server/server/services/agents/types.js.map +1 -0
- package/dist/server/server/websocket/index.js +85 -0
- package/dist/server/server/websocket/index.js.map +1 -0
- package/dist/server/services/AIService.d.ts +30 -0
- package/dist/server/services/AIService.d.ts.map +1 -0
- package/dist/server/services/AIService.js +216 -0
- package/dist/server/services/AIService.js.map +1 -0
- package/dist/server/services/FileWatcher.d.ts +10 -0
- package/dist/server/services/FileWatcher.d.ts.map +1 -0
- package/dist/server/services/FileWatcher.js +62 -0
- package/dist/server/services/FileWatcher.js.map +1 -0
- package/dist/server/services/WorkflowService.d.ts +54 -0
- package/dist/server/services/WorkflowService.d.ts.map +1 -0
- package/dist/server/services/WorkflowService.js +323 -0
- package/dist/server/services/WorkflowService.js.map +1 -0
- package/dist/server/shared/constants.js +175 -0
- package/dist/server/shared/constants.js.map +1 -0
- package/dist/server/shared/types.js +3 -0
- package/dist/server/shared/types.js.map +1 -0
- package/dist/server/websocket/index.d.ts +10 -0
- package/dist/server/websocket/index.d.ts.map +1 -0
- package/dist/server/websocket/index.js +85 -0
- package/dist/server/websocket/index.js.map +1 -0
- package/index.html +19 -0
- package/package.json +96 -0
- package/playwright.config.ts +27 -0
- package/postcss.config.js +6 -0
- package/public/vite.svg +9 -0
- package/src/client/App.tsx +520 -0
- package/src/client/components/Canvas/Canvas.tsx +405 -0
- package/src/client/components/Canvas/ExecutionOverlay.tsx +847 -0
- package/src/client/components/Canvas/NodeContextMenu.tsx +188 -0
- package/src/client/components/Canvas/OutputNode.tsx +111 -0
- package/src/client/components/Canvas/StepNode.tsx +106 -0
- package/src/client/components/Canvas/SubWorkflowNode.tsx +141 -0
- package/src/client/components/Canvas/Toolbar.tsx +189 -0
- package/src/client/components/Canvas/TriggerNode.tsx +128 -0
- package/src/client/components/Editor/InputsEditor.tsx +458 -0
- package/src/client/components/Editor/NewStepWizard.tsx +344 -0
- package/src/client/components/Editor/StepEditor.tsx +532 -0
- package/src/client/components/Editor/YamlEditor.tsx +160 -0
- package/src/client/components/Panels/PropertiesPanel.tsx +589 -0
- package/src/client/components/Prompt/ChangePreview.tsx +281 -0
- package/src/client/components/Prompt/PromptHistoryPanel.tsx +209 -0
- package/src/client/components/Prompt/PromptInput.tsx +108 -0
- package/src/client/components/Sidebar/Sidebar.tsx +343 -0
- package/src/client/components/common/Breadcrumb.tsx +40 -0
- package/src/client/components/common/Button.tsx +68 -0
- package/src/client/components/common/ContextMenu.tsx +202 -0
- package/src/client/components/common/KeyboardShortcuts.tsx +143 -0
- package/src/client/components/common/Modal.tsx +93 -0
- package/src/client/components/common/Tabs.tsx +57 -0
- package/src/client/components/common/ThemeToggle.tsx +63 -0
- package/src/client/components/index.ts +32 -0
- package/src/client/hooks/index.ts +4 -0
- package/src/client/hooks/useAIPrompt.ts +108 -0
- package/src/client/hooks/useCanvas.ts +247 -0
- package/src/client/hooks/useWebSocket.ts +164 -0
- package/src/client/hooks/useWorkflow.ts +138 -0
- package/src/client/main.tsx +10 -0
- package/src/client/stores/canvasStore.ts +348 -0
- package/src/client/stores/editorStore.ts +133 -0
- package/src/client/stores/executionStore.ts +440 -0
- package/src/client/stores/index.ts +4 -0
- package/src/client/stores/layoutStore.ts +103 -0
- package/src/client/stores/navigationStore.ts +49 -0
- package/src/client/stores/promptStore.ts +113 -0
- package/src/client/stores/themeStore.ts +75 -0
- package/src/client/stores/workflowStore.ts +177 -0
- package/src/client/styles/globals.css +346 -0
- package/src/client/utils/cn.ts +9 -0
- package/src/client/utils/index.ts +4 -0
- package/src/client/utils/serviceIcons.tsx +64 -0
- package/src/client/utils/stepValidation.ts +155 -0
- package/src/client/utils/workflowToGraph.ts +299 -0
- package/src/server/index.ts +114 -0
- package/src/server/routes/ai.ts +91 -0
- package/src/server/routes/execute.ts +71 -0
- package/src/server/routes/tools.ts +564 -0
- package/src/server/routes/workflows.ts +106 -0
- package/src/server/services/AIService.ts +105 -0
- package/src/server/services/FileWatcher.ts +69 -0
- package/src/server/services/WorkflowService.ts +441 -0
- package/src/server/services/agents/claude-code-provider.ts +320 -0
- package/src/server/services/agents/claude-provider.ts +248 -0
- package/src/server/services/agents/copilot-provider.ts +311 -0
- package/src/server/services/agents/demo-provider.ts +184 -0
- package/src/server/services/agents/index.ts +31 -0
- package/src/server/services/agents/ollama-provider.ts +267 -0
- package/src/server/services/agents/prompts.ts +482 -0
- package/src/server/services/agents/registry.ts +289 -0
- package/src/server/services/agents/types.ts +146 -0
- package/src/server/websocket/index.ts +104 -0
- package/src/shared/constants.ts +180 -0
- package/src/shared/types.ts +179 -0
- package/tailwind.config.ts +73 -0
- package/tests/e2e/app.spec.ts +90 -0
- package/tests/e2e/canvas.spec.ts +128 -0
- package/tests/e2e/workflow.spec.ts +185 -0
- package/tests/integration/api.test.ts +250 -0
- package/tests/integration/testApp.ts +31 -0
- package/tests/setup.ts +37 -0
- package/tests/unit/canvasStore.test.ts +502 -0
- package/tests/unit/components.test.tsx +151 -0
- package/tests/unit/executionStore.test.ts +527 -0
- package/tests/unit/layoutStore.test.ts +194 -0
- package/tests/unit/navigationStore.test.ts +152 -0
- package/tests/unit/stepValidation.test.ts +226 -0
- package/tests/unit/themeStore.test.ts +141 -0
- package/tests/unit/workflowToGraph.test.ts +289 -0
- package/tsconfig.json +29 -0
- package/tsconfig.server.json +28 -0
- package/vite.config.ts +31 -0
- package/vitest.config.ts +26 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Router, type Router as RouterType } from 'express';
|
|
2
|
+
import { WorkflowService } from '../services/WorkflowService.js';
|
|
3
|
+
|
|
4
|
+
const router: RouterType = Router();
|
|
5
|
+
const workflowService = new WorkflowService();
|
|
6
|
+
|
|
7
|
+
// List all workflows
|
|
8
|
+
router.get('/', async (_req, res) => {
|
|
9
|
+
try {
|
|
10
|
+
const workflows = await workflowService.listWorkflows();
|
|
11
|
+
res.json({ workflows });
|
|
12
|
+
} catch (error) {
|
|
13
|
+
res.status(500).json({
|
|
14
|
+
error: 'Failed to list workflows',
|
|
15
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Get a specific workflow
|
|
21
|
+
router.get('/:path(*)', async (req, res) => {
|
|
22
|
+
try {
|
|
23
|
+
const workflowPath = decodeURIComponent((req.params as Record<string, string>)['path(*)']);
|
|
24
|
+
const workflow = await workflowService.getWorkflow(workflowPath);
|
|
25
|
+
|
|
26
|
+
if (!workflow) {
|
|
27
|
+
return res.status(404).json({ error: 'Workflow not found' });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
res.json({ workflow });
|
|
31
|
+
} catch (error) {
|
|
32
|
+
res.status(500).json({
|
|
33
|
+
error: 'Failed to get workflow',
|
|
34
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Create a new workflow
|
|
40
|
+
router.post('/', async (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const { name, template } = req.body;
|
|
43
|
+
|
|
44
|
+
if (!name) {
|
|
45
|
+
return res.status(400).json({ error: 'Name is required' });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const workflow = await workflowService.createWorkflow(name, template);
|
|
49
|
+
res.status(201).json({ workflow });
|
|
50
|
+
} catch (error) {
|
|
51
|
+
res.status(500).json({
|
|
52
|
+
error: 'Failed to create workflow',
|
|
53
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Update a workflow
|
|
59
|
+
router.put('/:path(*)', async (req, res) => {
|
|
60
|
+
try {
|
|
61
|
+
const workflowPath = decodeURIComponent((req.params as Record<string, string>)['path(*)']);
|
|
62
|
+
const { workflow } = req.body;
|
|
63
|
+
|
|
64
|
+
if (!workflow) {
|
|
65
|
+
return res.status(400).json({ error: 'Workflow data is required' });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const updated = await workflowService.updateWorkflow(workflowPath, workflow);
|
|
69
|
+
res.json({ workflow: updated });
|
|
70
|
+
} catch (error) {
|
|
71
|
+
res.status(500).json({
|
|
72
|
+
error: 'Failed to update workflow',
|
|
73
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Delete a workflow
|
|
79
|
+
router.delete('/:path(*)', async (req, res) => {
|
|
80
|
+
try {
|
|
81
|
+
const workflowPath = decodeURIComponent((req.params as Record<string, string>)['path(*)']);
|
|
82
|
+
await workflowService.deleteWorkflow(workflowPath);
|
|
83
|
+
res.json({ success: true });
|
|
84
|
+
} catch (error) {
|
|
85
|
+
res.status(500).json({
|
|
86
|
+
error: 'Failed to delete workflow',
|
|
87
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Get workflow execution history
|
|
93
|
+
router.get('/:path(*)/runs', async (req, res) => {
|
|
94
|
+
try {
|
|
95
|
+
const workflowPath = decodeURIComponent((req.params as Record<string, string>)['path(*)']);
|
|
96
|
+
const runs = await workflowService.getExecutionHistory(workflowPath);
|
|
97
|
+
res.json({ runs });
|
|
98
|
+
} catch (error) {
|
|
99
|
+
res.status(500).json({
|
|
100
|
+
error: 'Failed to get execution history',
|
|
101
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export { router as workflowRoutes };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Service - Backwards-compatible wrapper around the Agent Registry
|
|
3
|
+
*
|
|
4
|
+
* This service provides the same interface as before but now supports
|
|
5
|
+
* multiple AI backends through the agent provider system.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { getAgentRegistry, type AgentRegistry, type PromptHistoryItem } from './agents/index.js';
|
|
9
|
+
|
|
10
|
+
interface Workflow {
|
|
11
|
+
metadata: any;
|
|
12
|
+
steps: any[];
|
|
13
|
+
tools?: Record<string, any>;
|
|
14
|
+
inputs?: Record<string, any>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface PromptResult {
|
|
18
|
+
explanation: string;
|
|
19
|
+
workflow?: Workflow;
|
|
20
|
+
diff?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class AIService {
|
|
24
|
+
private registry: AgentRegistry;
|
|
25
|
+
private initialized: boolean = false;
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
this.registry = getAgentRegistry();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Initialize the service with auto-detection of available providers
|
|
33
|
+
*/
|
|
34
|
+
async initialize(): Promise<void> {
|
|
35
|
+
if (!this.initialized) {
|
|
36
|
+
await this.registry.autoDetectProvider();
|
|
37
|
+
this.initialized = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Process a prompt to modify a workflow
|
|
43
|
+
*/
|
|
44
|
+
async processPrompt(prompt: string, workflow: Workflow): Promise<PromptResult> {
|
|
45
|
+
await this.initialize();
|
|
46
|
+
return this.registry.processPrompt(prompt, workflow);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Stream a prompt response (if supported by the active provider)
|
|
51
|
+
*/
|
|
52
|
+
async streamPrompt(
|
|
53
|
+
prompt: string,
|
|
54
|
+
workflow: Workflow,
|
|
55
|
+
onChunk: (chunk: string) => void
|
|
56
|
+
): Promise<PromptResult> {
|
|
57
|
+
await this.initialize();
|
|
58
|
+
return this.registry.streamPrompt(prompt, workflow, onChunk);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get prompt history
|
|
63
|
+
*/
|
|
64
|
+
async getHistory(): Promise<PromptHistoryItem[]> {
|
|
65
|
+
return this.registry.getHistory(20);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get suggestions for the current workflow
|
|
70
|
+
*/
|
|
71
|
+
async getSuggestions(
|
|
72
|
+
workflow: Workflow,
|
|
73
|
+
selectedStepId?: string
|
|
74
|
+
): Promise<string[]> {
|
|
75
|
+
await this.initialize();
|
|
76
|
+
return this.registry.getSuggestions(workflow, selectedStepId);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get the current provider status
|
|
81
|
+
*/
|
|
82
|
+
getStatus(): {
|
|
83
|
+
activeProvider: string;
|
|
84
|
+
providers: Array<{ id: string; name: string; ready: boolean; model?: string; error?: string }>;
|
|
85
|
+
} {
|
|
86
|
+
return this.registry.getStatus();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Switch to a different provider
|
|
91
|
+
*/
|
|
92
|
+
async setProvider(
|
|
93
|
+
providerId: string,
|
|
94
|
+
config?: { apiKey?: string; baseUrl?: string; model?: string }
|
|
95
|
+
): Promise<boolean> {
|
|
96
|
+
return this.registry.setActiveProvider(providerId, config);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get the registry for direct access to providers
|
|
101
|
+
*/
|
|
102
|
+
getRegistry(): AgentRegistry {
|
|
103
|
+
return this.registry;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { watch, type FSWatcher } from 'chokidar';
|
|
2
|
+
import type { Server as SocketIOServer } from 'socket.io';
|
|
3
|
+
|
|
4
|
+
export class FileWatcher {
|
|
5
|
+
private watcher: FSWatcher;
|
|
6
|
+
private io: SocketIOServer;
|
|
7
|
+
|
|
8
|
+
constructor(baseDir: string, io: SocketIOServer) {
|
|
9
|
+
this.io = io;
|
|
10
|
+
|
|
11
|
+
// Watch for workflow files
|
|
12
|
+
this.watcher = watch(['**/*.md', '**/*.yaml', '**/*.yml'], {
|
|
13
|
+
cwd: baseDir,
|
|
14
|
+
ignored: [
|
|
15
|
+
'**/node_modules/**',
|
|
16
|
+
'**/dist/**',
|
|
17
|
+
'**/.git/**',
|
|
18
|
+
'**/.*',
|
|
19
|
+
],
|
|
20
|
+
persistent: true,
|
|
21
|
+
ignoreInitial: true,
|
|
22
|
+
awaitWriteFinish: {
|
|
23
|
+
stabilityThreshold: 300,
|
|
24
|
+
pollInterval: 100,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.setupListeners();
|
|
29
|
+
console.log(`File watcher started for: ${baseDir}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private setupListeners() {
|
|
33
|
+
this.watcher.on('change', (path) => {
|
|
34
|
+
console.log(`File changed: ${path}`);
|
|
35
|
+
this.io.emit('workflow:updated', {
|
|
36
|
+
path,
|
|
37
|
+
event: 'change',
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.watcher.on('add', (path) => {
|
|
43
|
+
console.log(`File added: ${path}`);
|
|
44
|
+
this.io.emit('workflow:updated', {
|
|
45
|
+
path,
|
|
46
|
+
event: 'add',
|
|
47
|
+
timestamp: new Date().toISOString(),
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
this.watcher.on('unlink', (path) => {
|
|
52
|
+
console.log(`File removed: ${path}`);
|
|
53
|
+
this.io.emit('workflow:updated', {
|
|
54
|
+
path,
|
|
55
|
+
event: 'remove',
|
|
56
|
+
timestamp: new Date().toISOString(),
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
this.watcher.on('error', (error) => {
|
|
61
|
+
console.error('File watcher error:', error);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
stop() {
|
|
66
|
+
this.watcher.close();
|
|
67
|
+
console.log('File watcher stopped');
|
|
68
|
+
}
|
|
69
|
+
}
|