@marktoflow/gui 2.0.0-alpha.5 → 2.0.2
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 +48 -180
- package/dist/client/assets/index-DQeR1ew6.css +1 -0
- package/dist/client/assets/index-LbIVPHbD.js +833 -0
- package/dist/client/assets/index-LbIVPHbD.js.map +1 -0
- package/dist/client/index.html +2 -2
- package/dist/client/marktoflow-logo.png +0 -0
- package/dist/server/index.js +31 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/admin.js +95 -0
- package/dist/server/routes/admin.js.map +1 -0
- package/dist/server/routes/ai.js +2 -2
- package/dist/server/routes/ai.js.map +1 -1
- package/dist/server/routes/collaboration.js +104 -0
- package/dist/server/routes/collaboration.js.map +1 -0
- package/dist/server/routes/execute.js +181 -14
- package/dist/server/routes/execute.js.map +1 -1
- package/dist/server/routes/form.js +160 -0
- package/dist/server/routes/form.js.map +1 -0
- package/dist/server/routes/settings.js +90 -0
- package/dist/server/routes/settings.js.map +1 -0
- package/dist/server/routes/templates.js +106 -0
- package/dist/server/routes/templates.js.map +1 -0
- package/dist/server/routes/versions.js +101 -0
- package/dist/server/routes/versions.js.map +1 -0
- package/dist/server/services/AIService.js +85 -2
- package/dist/server/services/AIService.js.map +1 -1
- package/dist/server/services/ExecutionManager.js +571 -0
- package/dist/server/services/ExecutionManager.js.map +1 -0
- package/dist/server/services/VersionService.js +65 -0
- package/dist/server/services/VersionService.js.map +1 -0
- package/dist/server/services/WorkflowService.js +8 -2
- package/dist/server/services/WorkflowService.js.map +1 -1
- package/dist/server/services/agents/copilot-provider.js +32 -0
- package/dist/server/services/agents/copilot-provider.js.map +1 -1
- package/dist/server/websocket/index.js +42 -0
- package/dist/server/websocket/index.js.map +1 -1
- package/dist/shared/constants.js +9 -0
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/settings.js +51 -0
- package/dist/shared/settings.js.map +1 -0
- package/package.json +14 -10
- package/public/marktoflow-logo.png +0 -0
- package/tests/integration/fixtures/test-workflow.md +6 -0
- package/.turbo/turbo-build.log +0 -42
- package/dist/client/assets/index-CM44OayM.js +0 -704
- package/dist/client/assets/index-CM44OayM.js.map +0 -1
- package/dist/client/assets/index-Dru63gi6.css +0 -1
- package/marktoflow-gui-2.0.0-alpha.5.tgz +0 -0
- package/playwright.config.ts +0 -27
- package/postcss.config.js +0 -6
- package/src/client/App.tsx +0 -520
- package/src/client/components/Canvas/Canvas.tsx +0 -425
- package/src/client/components/Canvas/ExecutionOverlay.tsx +0 -935
- package/src/client/components/Canvas/ForEachNode.tsx +0 -152
- package/src/client/components/Canvas/IfElseNode.tsx +0 -141
- package/src/client/components/Canvas/NodeContextMenu.tsx +0 -192
- package/src/client/components/Canvas/OutputNode.tsx +0 -111
- package/src/client/components/Canvas/ParallelNode.tsx +0 -157
- package/src/client/components/Canvas/StepNode.tsx +0 -106
- package/src/client/components/Canvas/SubWorkflowNode.tsx +0 -141
- package/src/client/components/Canvas/SwitchNode.tsx +0 -185
- package/src/client/components/Canvas/Toolbar.tsx +0 -227
- package/src/client/components/Canvas/TransformNode.tsx +0 -194
- package/src/client/components/Canvas/TriggerNode.tsx +0 -128
- package/src/client/components/Canvas/TryCatchNode.tsx +0 -164
- package/src/client/components/Canvas/WhileNode.tsx +0 -161
- package/src/client/components/Canvas/index.ts +0 -24
- package/src/client/components/Debug/VariableInspector.tsx +0 -148
- package/src/client/components/Editor/InputsEditor.tsx +0 -458
- package/src/client/components/Editor/NewStepWizard.tsx +0 -344
- package/src/client/components/Editor/StepEditor.tsx +0 -532
- package/src/client/components/Editor/YamlEditor.tsx +0 -160
- package/src/client/components/Panels/PropertiesPanel.tsx +0 -589
- package/src/client/components/Prompt/ChangePreview.tsx +0 -281
- package/src/client/components/Prompt/PromptHistoryPanel.tsx +0 -209
- package/src/client/components/Prompt/PromptInput.tsx +0 -110
- package/src/client/components/Settings/ProviderSwitcher.tsx +0 -228
- package/src/client/components/Sidebar/ImportDialog.tsx +0 -257
- package/src/client/components/Sidebar/Sidebar.tsx +0 -362
- package/src/client/components/common/Breadcrumb.tsx +0 -40
- package/src/client/components/common/Button.tsx +0 -68
- package/src/client/components/common/ContextMenu.tsx +0 -202
- package/src/client/components/common/KeyboardShortcuts.tsx +0 -149
- package/src/client/components/common/Modal.tsx +0 -93
- package/src/client/components/common/Tabs.tsx +0 -57
- package/src/client/components/common/ThemeToggle.tsx +0 -63
- package/src/client/components/index.ts +0 -32
- package/src/client/hooks/index.ts +0 -4
- package/src/client/hooks/useAIPrompt.ts +0 -108
- package/src/client/hooks/useCanvas.ts +0 -247
- package/src/client/hooks/useWebSocket.ts +0 -164
- package/src/client/hooks/useWorkflow.ts +0 -138
- package/src/client/main.tsx +0 -10
- package/src/client/stores/agentStore.ts +0 -109
- package/src/client/stores/canvasStore.ts +0 -348
- package/src/client/stores/editorStore.ts +0 -133
- package/src/client/stores/executionStore.ts +0 -502
- package/src/client/stores/index.ts +0 -4
- package/src/client/stores/layoutStore.ts +0 -103
- package/src/client/stores/navigationStore.ts +0 -49
- package/src/client/stores/promptStore.ts +0 -113
- package/src/client/stores/themeStore.ts +0 -75
- package/src/client/stores/workflowStore.ts +0 -185
- package/src/client/styles/globals.css +0 -452
- package/src/client/utils/cn.ts +0 -9
- package/src/client/utils/index.ts +0 -4
- package/src/client/utils/platform.ts +0 -46
- package/src/client/utils/serviceIcons.tsx +0 -97
- package/src/client/utils/stepValidation.ts +0 -155
- package/src/client/utils/workflowToGraph.ts +0 -523
- package/src/server/index.ts +0 -137
- package/src/server/routes/ai.ts +0 -91
- package/src/server/routes/execute.ts +0 -71
- package/src/server/routes/executions.ts +0 -136
- package/src/server/routes/tools.ts +0 -970
- package/src/server/routes/workflows.ts +0 -147
- package/src/server/services/AIService.ts +0 -105
- package/src/server/services/FileWatcher.ts +0 -69
- package/src/server/services/WorkflowService.ts +0 -601
- package/src/server/services/agents/claude-code-provider.ts +0 -320
- package/src/server/services/agents/claude-provider.ts +0 -248
- package/src/server/services/agents/codex-provider.ts +0 -398
- package/src/server/services/agents/copilot-provider.ts +0 -311
- package/src/server/services/agents/demo-provider.ts +0 -184
- package/src/server/services/agents/index.ts +0 -31
- package/src/server/services/agents/ollama-provider.ts +0 -267
- package/src/server/services/agents/prompts.ts +0 -509
- package/src/server/services/agents/registry.ts +0 -310
- package/src/server/services/agents/types.ts +0 -146
- package/src/server/websocket/index.ts +0 -117
- package/src/shared/constants.ts +0 -180
- package/src/shared/types.ts +0 -179
- package/tailwind.config.ts +0 -73
- package/tests/e2e/app.spec.ts +0 -90
- package/tests/e2e/canvas.spec.ts +0 -128
- package/tests/e2e/workflow.spec.ts +0 -185
- package/tests/integration/api.test.ts +0 -452
- package/tests/integration/testApp.ts +0 -31
- package/tests/setup.ts +0 -72
- package/tests/unit/ForEachNode.test.tsx +0 -308
- package/tests/unit/IfElseNode.test.tsx +0 -235
- package/tests/unit/ParallelNode.test.tsx +0 -344
- package/tests/unit/SwitchNode.test.tsx +0 -327
- package/tests/unit/TransformNode.test.tsx +0 -386
- package/tests/unit/TryCatchNode.test.tsx +0 -243
- package/tests/unit/WhileNode.test.tsx +0 -230
- package/tests/unit/agentStore.test.ts +0 -218
- package/tests/unit/canvasStore.test.ts +0 -502
- package/tests/unit/codexProvider.test.ts +0 -399
- package/tests/unit/components.test.tsx +0 -151
- package/tests/unit/executionStore.test.ts +0 -567
- package/tests/unit/layoutStore.test.ts +0 -194
- package/tests/unit/navigationStore.test.ts +0 -152
- package/tests/unit/platform.test.ts +0 -118
- package/tests/unit/serviceIcons.test.ts +0 -197
- package/tests/unit/stepValidation.test.ts +0 -226
- package/tests/unit/themeStore.test.ts +0 -141
- package/tests/unit/workflowToGraph.test.ts +0 -311
- package/tsconfig.json +0 -29
- package/tsconfig.server.json +0 -28
- package/vite.config.ts +0 -31
- package/vitest.config.ts +0 -26
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand';
|
|
2
|
-
import { useWorkflowStore } from './workflowStore';
|
|
3
|
-
|
|
4
|
-
export interface PromptHistoryItem {
|
|
5
|
-
prompt: string;
|
|
6
|
-
response: string;
|
|
7
|
-
timestamp: Date;
|
|
8
|
-
success: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface PromptState {
|
|
12
|
-
isProcessing: boolean;
|
|
13
|
-
history: PromptHistoryItem[];
|
|
14
|
-
lastError: string | null;
|
|
15
|
-
pendingChanges: any | null;
|
|
16
|
-
|
|
17
|
-
sendPrompt: (prompt: string) => Promise<void>;
|
|
18
|
-
acceptChanges: () => void;
|
|
19
|
-
rejectChanges: () => void;
|
|
20
|
-
clearHistory: () => void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const usePromptStore = create<PromptState>((set, get) => ({
|
|
24
|
-
isProcessing: false,
|
|
25
|
-
history: [],
|
|
26
|
-
lastError: null,
|
|
27
|
-
pendingChanges: null,
|
|
28
|
-
|
|
29
|
-
sendPrompt: async (prompt: string) => {
|
|
30
|
-
set({ isProcessing: true, lastError: null });
|
|
31
|
-
|
|
32
|
-
const workflow = useWorkflowStore.getState().currentWorkflow;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch('/api/ai/prompt', {
|
|
36
|
-
method: 'POST',
|
|
37
|
-
headers: { 'Content-Type': 'application/json' },
|
|
38
|
-
body: JSON.stringify({
|
|
39
|
-
prompt,
|
|
40
|
-
workflow,
|
|
41
|
-
}),
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
if (!response.ok) {
|
|
45
|
-
throw new Error('Failed to process prompt');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const data = await response.json();
|
|
49
|
-
|
|
50
|
-
// Add to history
|
|
51
|
-
const historyItem: PromptHistoryItem = {
|
|
52
|
-
prompt,
|
|
53
|
-
response: data.explanation,
|
|
54
|
-
timestamp: new Date(),
|
|
55
|
-
success: true,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
set({
|
|
59
|
-
history: [historyItem, ...get().history].slice(0, 20),
|
|
60
|
-
pendingChanges: data.workflow,
|
|
61
|
-
isProcessing: false,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Auto-accept for now (in production, show diff first)
|
|
65
|
-
if (data.workflow) {
|
|
66
|
-
get().acceptChanges();
|
|
67
|
-
}
|
|
68
|
-
} catch (error) {
|
|
69
|
-
const errorMessage =
|
|
70
|
-
error instanceof Error ? error.message : 'Unknown error';
|
|
71
|
-
|
|
72
|
-
const historyItem: PromptHistoryItem = {
|
|
73
|
-
prompt,
|
|
74
|
-
response: errorMessage,
|
|
75
|
-
timestamp: new Date(),
|
|
76
|
-
success: false,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
set({
|
|
80
|
-
history: [historyItem, ...get().history].slice(0, 20),
|
|
81
|
-
lastError: errorMessage,
|
|
82
|
-
isProcessing: false,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Demo: simulate AI response for testing without backend
|
|
86
|
-
console.log('AI Prompt (demo mode):', prompt);
|
|
87
|
-
console.log('Current workflow:', workflow);
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
acceptChanges: () => {
|
|
92
|
-
const pendingChanges = get().pendingChanges;
|
|
93
|
-
if (!pendingChanges) return;
|
|
94
|
-
|
|
95
|
-
// Update workflow store
|
|
96
|
-
useWorkflowStore.getState().saveWorkflow(pendingChanges);
|
|
97
|
-
|
|
98
|
-
// TODO: Convert workflow to graph and update canvas
|
|
99
|
-
// const { nodes, edges } = workflowToGraph(pendingChanges);
|
|
100
|
-
// useCanvasStore.getState().setNodes(nodes);
|
|
101
|
-
// useCanvasStore.getState().setEdges(edges);
|
|
102
|
-
|
|
103
|
-
set({ pendingChanges: null });
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
rejectChanges: () => {
|
|
107
|
-
set({ pendingChanges: null });
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
clearHistory: () => {
|
|
111
|
-
set({ history: [] });
|
|
112
|
-
},
|
|
113
|
-
}));
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand';
|
|
2
|
-
import { persist } from 'zustand/middleware';
|
|
3
|
-
|
|
4
|
-
export type Theme = 'dark' | 'light' | 'system';
|
|
5
|
-
|
|
6
|
-
interface ThemeState {
|
|
7
|
-
theme: Theme;
|
|
8
|
-
resolvedTheme: 'dark' | 'light';
|
|
9
|
-
setTheme: (theme: Theme) => void;
|
|
10
|
-
toggleTheme: () => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Check system preference
|
|
14
|
-
function getSystemTheme(): 'dark' | 'light' {
|
|
15
|
-
if (typeof window === 'undefined') return 'dark';
|
|
16
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Apply theme to document
|
|
20
|
-
function applyTheme(resolvedTheme: 'dark' | 'light') {
|
|
21
|
-
if (typeof document === 'undefined') return;
|
|
22
|
-
|
|
23
|
-
const root = document.documentElement;
|
|
24
|
-
if (resolvedTheme === 'dark') {
|
|
25
|
-
root.classList.add('dark');
|
|
26
|
-
root.classList.remove('light');
|
|
27
|
-
} else {
|
|
28
|
-
root.classList.add('light');
|
|
29
|
-
root.classList.remove('dark');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const useThemeStore = create<ThemeState>()(
|
|
34
|
-
persist(
|
|
35
|
-
(set, get) => ({
|
|
36
|
-
theme: 'dark',
|
|
37
|
-
resolvedTheme: 'dark',
|
|
38
|
-
|
|
39
|
-
setTheme: (theme: Theme) => {
|
|
40
|
-
const resolvedTheme = theme === 'system' ? getSystemTheme() : theme;
|
|
41
|
-
applyTheme(resolvedTheme);
|
|
42
|
-
set({ theme, resolvedTheme });
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
toggleTheme: () => {
|
|
46
|
-
const { theme } = get();
|
|
47
|
-
const newTheme: Theme = theme === 'dark' ? 'light' : 'dark';
|
|
48
|
-
const resolvedTheme = newTheme === 'system' ? getSystemTheme() : newTheme;
|
|
49
|
-
applyTheme(resolvedTheme);
|
|
50
|
-
set({ theme: newTheme, resolvedTheme: resolvedTheme });
|
|
51
|
-
},
|
|
52
|
-
}),
|
|
53
|
-
{
|
|
54
|
-
name: 'marktoflow-theme',
|
|
55
|
-
onRehydrateStorage: () => (state) => {
|
|
56
|
-
// Apply theme when storage is rehydrated
|
|
57
|
-
if (state) {
|
|
58
|
-
const resolvedTheme = state.theme === 'system' ? getSystemTheme() : state.theme;
|
|
59
|
-
applyTheme(resolvedTheme);
|
|
60
|
-
state.resolvedTheme = resolvedTheme;
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
}
|
|
64
|
-
)
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
// Listen for system theme changes
|
|
68
|
-
if (typeof window !== 'undefined') {
|
|
69
|
-
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
70
|
-
const { theme, setTheme } = useThemeStore.getState();
|
|
71
|
-
if (theme === 'system') {
|
|
72
|
-
setTheme('system'); // Re-resolve the theme
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand';
|
|
2
|
-
import type { Workflow, WorkflowListItem } from '@shared/types';
|
|
3
|
-
|
|
4
|
-
interface WorkflowState {
|
|
5
|
-
workflows: WorkflowListItem[];
|
|
6
|
-
selectedWorkflow: string | null;
|
|
7
|
-
currentWorkflow: Workflow | null;
|
|
8
|
-
isLoading: boolean;
|
|
9
|
-
error: string | null;
|
|
10
|
-
|
|
11
|
-
loadWorkflows: () => Promise<void>;
|
|
12
|
-
fetchWorkflows: () => Promise<void>; // Alias for compatibility
|
|
13
|
-
selectWorkflow: (path: string) => void;
|
|
14
|
-
loadWorkflow: (path: string) => Promise<void>;
|
|
15
|
-
saveWorkflow: (workflow: Workflow) => Promise<void>;
|
|
16
|
-
createWorkflow: (name: string) => Promise<void>;
|
|
17
|
-
deleteWorkflow: (path: string) => Promise<void>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Demo workflows for initial state
|
|
21
|
-
const demoWorkflows: WorkflowListItem[] = [
|
|
22
|
-
{ path: 'examples/code-review/workflow.md', name: 'Code Review' },
|
|
23
|
-
{ path: 'examples/daily-standup/workflow.md', name: 'Daily Standup' },
|
|
24
|
-
{ path: 'examples/incident-response/workflow.md', name: 'Incident Response' },
|
|
25
|
-
{ path: 'examples/sprint-planning/workflow.md', name: 'Sprint Planning' },
|
|
26
|
-
{ path: 'examples/dependency-update/workflow.md', name: 'Dependency Update' },
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const demoWorkflow: Workflow = {
|
|
30
|
-
metadata: {
|
|
31
|
-
id: 'code-review',
|
|
32
|
-
name: 'Code Review',
|
|
33
|
-
version: '1.0.0',
|
|
34
|
-
description: 'Automatically review pull requests using Claude AI',
|
|
35
|
-
author: 'Marktoflow',
|
|
36
|
-
tags: ['github', 'ai', 'code-review'],
|
|
37
|
-
},
|
|
38
|
-
steps: [
|
|
39
|
-
{
|
|
40
|
-
id: 'fetch_pr',
|
|
41
|
-
name: 'Fetch PR Details',
|
|
42
|
-
action: 'github.pulls.get',
|
|
43
|
-
inputs: {
|
|
44
|
-
owner: "{{ inputs.repo.split('/')[0] }}",
|
|
45
|
-
repo: "{{ inputs.repo.split('/')[1] }}",
|
|
46
|
-
pull_number: '{{ inputs.pr_number }}',
|
|
47
|
-
},
|
|
48
|
-
outputVariable: 'pr_details',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
id: 'get_files',
|
|
52
|
-
name: 'Get Changed Files',
|
|
53
|
-
action: 'github.pulls.listFiles',
|
|
54
|
-
inputs: {
|
|
55
|
-
owner: "{{ inputs.repo.split('/')[0] }}",
|
|
56
|
-
repo: "{{ inputs.repo.split('/')[1] }}",
|
|
57
|
-
pull_number: '{{ inputs.pr_number }}',
|
|
58
|
-
},
|
|
59
|
-
outputVariable: 'changed_files',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: 'analyze',
|
|
63
|
-
name: 'Analyze Changes',
|
|
64
|
-
action: 'claude.analyze',
|
|
65
|
-
inputs: {
|
|
66
|
-
prompt: 'Review the following code changes',
|
|
67
|
-
context: '{{ changed_files }}',
|
|
68
|
-
},
|
|
69
|
-
outputVariable: 'analysis',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
id: 'post_review',
|
|
73
|
-
name: 'Post Review',
|
|
74
|
-
action: 'github.pulls.createReview',
|
|
75
|
-
inputs: {
|
|
76
|
-
owner: "{{ inputs.repo.split('/')[0] }}",
|
|
77
|
-
repo: "{{ inputs.repo.split('/')[1] }}",
|
|
78
|
-
pull_number: '{{ inputs.pr_number }}',
|
|
79
|
-
body: '{{ analysis.summary }}',
|
|
80
|
-
event: 'COMMENT',
|
|
81
|
-
},
|
|
82
|
-
outputVariable: 'review_result',
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
export const useWorkflowStore = create<WorkflowState>((set, get) => ({
|
|
88
|
-
workflows: demoWorkflows,
|
|
89
|
-
selectedWorkflow: null,
|
|
90
|
-
currentWorkflow: null,
|
|
91
|
-
isLoading: false,
|
|
92
|
-
error: null,
|
|
93
|
-
|
|
94
|
-
loadWorkflows: async () => {
|
|
95
|
-
set({ isLoading: true, error: null });
|
|
96
|
-
try {
|
|
97
|
-
const response = await fetch('/api/workflows');
|
|
98
|
-
if (!response.ok) throw new Error('Failed to load workflows');
|
|
99
|
-
const data = await response.json();
|
|
100
|
-
console.log('Loaded workflows:', data.workflows.length);
|
|
101
|
-
set({ workflows: data.workflows, isLoading: false });
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.error('Failed to load workflows, using demo data:', error);
|
|
104
|
-
// Use demo data if API fails
|
|
105
|
-
set({ workflows: demoWorkflows, isLoading: false });
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
// Alias for compatibility with components
|
|
110
|
-
fetchWorkflows: async () => {
|
|
111
|
-
await get().loadWorkflows();
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
selectWorkflow: (path) => {
|
|
115
|
-
set({ selectedWorkflow: path });
|
|
116
|
-
get().loadWorkflow(path);
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
loadWorkflow: async (path) => {
|
|
120
|
-
set({ isLoading: true, error: null });
|
|
121
|
-
try {
|
|
122
|
-
const response = await fetch(`/api/workflows/${encodeURIComponent(path)}`);
|
|
123
|
-
if (!response.ok) throw new Error('Failed to load workflow');
|
|
124
|
-
const data = await response.json();
|
|
125
|
-
set({ currentWorkflow: data.workflow, isLoading: false });
|
|
126
|
-
} catch (error) {
|
|
127
|
-
// Use demo data if API fails
|
|
128
|
-
set({ currentWorkflow: demoWorkflow, isLoading: false });
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
saveWorkflow: async (workflow) => {
|
|
133
|
-
const path = get().selectedWorkflow;
|
|
134
|
-
if (!path) return;
|
|
135
|
-
|
|
136
|
-
set({ isLoading: true, error: null });
|
|
137
|
-
try {
|
|
138
|
-
const response = await fetch(`/api/workflows/${encodeURIComponent(path)}`, {
|
|
139
|
-
method: 'PUT',
|
|
140
|
-
headers: { 'Content-Type': 'application/json' },
|
|
141
|
-
body: JSON.stringify({ workflow }),
|
|
142
|
-
});
|
|
143
|
-
if (!response.ok) throw new Error('Failed to save workflow');
|
|
144
|
-
set({ currentWorkflow: workflow, isLoading: false });
|
|
145
|
-
} catch (error) {
|
|
146
|
-
set({ error: 'Failed to save workflow', isLoading: false });
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
createWorkflow: async (name) => {
|
|
151
|
-
set({ isLoading: true, error: null });
|
|
152
|
-
try {
|
|
153
|
-
const response = await fetch('/api/workflows', {
|
|
154
|
-
method: 'POST',
|
|
155
|
-
headers: { 'Content-Type': 'application/json' },
|
|
156
|
-
body: JSON.stringify({ name }),
|
|
157
|
-
});
|
|
158
|
-
if (!response.ok) throw new Error('Failed to create workflow');
|
|
159
|
-
const data = await response.json();
|
|
160
|
-
const workflows = [...get().workflows, data.workflow];
|
|
161
|
-
set({ workflows, selectedWorkflow: data.workflow.path, isLoading: false });
|
|
162
|
-
get().loadWorkflow(data.workflow.path);
|
|
163
|
-
} catch (error) {
|
|
164
|
-
set({ error: 'Failed to create workflow', isLoading: false });
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
deleteWorkflow: async (path) => {
|
|
169
|
-
set({ isLoading: true, error: null });
|
|
170
|
-
try {
|
|
171
|
-
const response = await fetch(`/api/workflows/${encodeURIComponent(path)}`, {
|
|
172
|
-
method: 'DELETE',
|
|
173
|
-
});
|
|
174
|
-
if (!response.ok) throw new Error('Failed to delete workflow');
|
|
175
|
-
const workflows = get().workflows.filter((w) => w.path !== path);
|
|
176
|
-
set({
|
|
177
|
-
workflows,
|
|
178
|
-
selectedWorkflow: workflows[0]?.path || null,
|
|
179
|
-
isLoading: false,
|
|
180
|
-
});
|
|
181
|
-
} catch (error) {
|
|
182
|
-
set({ error: 'Failed to delete workflow', isLoading: false });
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
}));
|