@marktoflow/gui 2.0.0-alpha.4 → 2.0.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/README.md +48 -170
- package/client.log +0 -0
- 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/{server/index.js → index.js} +53 -6
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/admin.js +95 -0
- package/dist/server/routes/admin.js.map +1 -0
- package/dist/server/{server/routes → routes}/ai.js +2 -2
- package/dist/server/{server/routes → 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 +230 -0
- package/dist/server/routes/execute.js.map +1 -0
- package/dist/server/routes/executions.js +125 -0
- package/dist/server/routes/executions.js.map +1 -0
- 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/{server/routes → routes}/workflows.js +37 -1
- package/dist/server/routes/workflows.js.map +1 -0
- package/dist/server/services/AIService.js +152 -0
- package/dist/server/services/AIService.js.map +1 -0
- 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/{server/services → services}/WorkflowService.js +166 -17
- package/dist/server/services/WorkflowService.js.map +1 -0
- package/dist/server/{server/services → services}/agents/copilot-provider.js +32 -0
- package/dist/server/services/agents/copilot-provider.js.map +1 -0
- package/dist/server/{server/websocket → websocket}/index.js +54 -0
- package/dist/server/websocket/index.js.map +1 -0
- package/dist/{server/shared → shared}/constants.js +9 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/settings.js +51 -0
- package/dist/shared/settings.js.map +1 -0
- package/package.json +32 -14
- package/public/marktoflow-logo.png +0 -0
- package/scripts/flatten-dist.js +69 -0
- package/server.log +0 -0
- package/tests/integration/fixtures/test-workflow.md +6 -0
- package/.turbo/turbo-build.log +0 -26
- package/dist/client/assets/index-C90Y_aBX.js +0 -678
- package/dist/client/assets/index-C90Y_aBX.js.map +0 -1
- package/dist/client/assets/index-CRWeQ3NN.css +0 -1
- package/dist/server/server/index.js.map +0 -1
- package/dist/server/server/routes/execute.js +0 -63
- package/dist/server/server/routes/execute.js.map +0 -1
- package/dist/server/server/routes/workflows.js.map +0 -1
- package/dist/server/server/services/AIService.js +0 -69
- package/dist/server/server/services/AIService.js.map +0 -1
- package/dist/server/server/services/WorkflowService.js.map +0 -1
- package/dist/server/server/services/agents/copilot-provider.js.map +0 -1
- package/dist/server/server/websocket/index.js.map +0 -1
- package/dist/server/shared/constants.js.map +0 -1
- 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 -423
- package/src/client/components/Canvas/ExecutionOverlay.tsx +0 -847
- package/src/client/components/Canvas/ForEachNode.tsx +0 -128
- package/src/client/components/Canvas/IfElseNode.tsx +0 -126
- package/src/client/components/Canvas/NodeContextMenu.tsx +0 -188
- package/src/client/components/Canvas/OutputNode.tsx +0 -111
- package/src/client/components/Canvas/ParallelNode.tsx +0 -140
- 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 -164
- package/src/client/components/Canvas/Toolbar.tsx +0 -189
- package/src/client/components/Canvas/TransformNode.tsx +0 -185
- 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 -129
- package/src/client/components/Canvas/index.ts +0 -24
- 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 -108
- package/src/client/components/Sidebar/Sidebar.tsx +0 -343
- 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 -143
- 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/canvasStore.ts +0 -348
- package/src/client/stores/editorStore.ts +0 -133
- package/src/client/stores/executionStore.ts +0 -440
- 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 -177
- package/src/client/styles/globals.css +0 -346
- package/src/client/utils/cn.ts +0 -9
- package/src/client/utils/index.ts +0 -4
- package/src/client/utils/serviceIcons.tsx +0 -97
- package/src/client/utils/stepValidation.ts +0 -155
- package/src/client/utils/workflowToGraph.ts +0 -299
- package/src/server/index.ts +0 -114
- package/src/server/routes/ai.ts +0 -91
- package/src/server/routes/execute.ts +0 -71
- package/src/server/routes/tools.ts +0 -970
- package/src/server/routes/workflows.ts +0 -106
- package/src/server/services/AIService.ts +0 -105
- package/src/server/services/FileWatcher.ts +0 -69
- package/src/server/services/WorkflowService.ts +0 -441
- 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 -104
- 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 -218
- package/tests/unit/IfElseNode.test.tsx +0 -188
- package/tests/unit/ParallelNode.test.tsx +0 -264
- package/tests/unit/SwitchNode.test.tsx +0 -252
- package/tests/unit/TransformNode.test.tsx +0 -386
- package/tests/unit/TryCatchNode.test.tsx +0 -243
- package/tests/unit/WhileNode.test.tsx +0 -226
- 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 -527
- package/tests/unit/layoutStore.test.ts +0 -194
- package/tests/unit/navigationStore.test.ts +0 -152
- 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 -289
- package/tsconfig.json +0 -29
- package/tsconfig.server.json +0 -28
- package/vite.config.ts +0 -31
- package/vitest.config.ts +0 -26
- /package/dist/server/{server/routes → routes}/tools.js +0 -0
- /package/dist/server/{server/routes → routes}/tools.js.map +0 -0
- /package/dist/server/{server/services → services}/FileWatcher.js +0 -0
- /package/dist/server/{server/services → services}/FileWatcher.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/claude-code-provider.js +0 -0
- /package/dist/server/{server/services → services}/agents/claude-code-provider.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/claude-provider.js +0 -0
- /package/dist/server/{server/services → services}/agents/claude-provider.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/codex-provider.js +0 -0
- /package/dist/server/{server/services → services}/agents/codex-provider.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/demo-provider.js +0 -0
- /package/dist/server/{server/services → services}/agents/demo-provider.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/index.js +0 -0
- /package/dist/server/{server/services → services}/agents/index.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/ollama-provider.js +0 -0
- /package/dist/server/{server/services → services}/agents/ollama-provider.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/prompts.js +0 -0
- /package/dist/server/{server/services → services}/agents/prompts.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/registry.js +0 -0
- /package/dist/server/{server/services → services}/agents/registry.js.map +0 -0
- /package/dist/server/{server/services → services}/agents/types.js +0 -0
- /package/dist/server/{server/services → services}/agents/types.js.map +0 -0
- /package/dist/{server/shared → shared}/types.js +0 -0
- /package/dist/{server/shared → shared}/types.js.map +0 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API routes for execution history
|
|
3
|
+
*/
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
import { getStateStore } from '../index.js';
|
|
6
|
+
export const executionRoutes = Router();
|
|
7
|
+
/**
|
|
8
|
+
* GET /api/executions
|
|
9
|
+
* List all executions with optional filtering
|
|
10
|
+
*/
|
|
11
|
+
executionRoutes.get('/', (req, res) => {
|
|
12
|
+
try {
|
|
13
|
+
const stateStore = getStateStore();
|
|
14
|
+
const { workflowId, status, limit, offset } = req.query;
|
|
15
|
+
// Helper to extract string from query param
|
|
16
|
+
const getString = (val) => {
|
|
17
|
+
if (typeof val === 'string')
|
|
18
|
+
return val;
|
|
19
|
+
if (Array.isArray(val) && val.length > 0 && typeof val[0] === 'string')
|
|
20
|
+
return val[0];
|
|
21
|
+
return undefined;
|
|
22
|
+
};
|
|
23
|
+
const workflowIdStr = getString(workflowId);
|
|
24
|
+
const statusStr = getString(status);
|
|
25
|
+
const limitNum = parseInt(getString(limit) || '50', 10);
|
|
26
|
+
const offsetNum = getString(offset) ? parseInt(getString(offset), 10) : undefined;
|
|
27
|
+
const executions = stateStore.listExecutions({
|
|
28
|
+
workflowId: workflowIdStr,
|
|
29
|
+
status: statusStr,
|
|
30
|
+
limit: limitNum,
|
|
31
|
+
offset: offsetNum,
|
|
32
|
+
});
|
|
33
|
+
res.json(executions);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error('Error listing executions:', error);
|
|
37
|
+
res.status(500).json({
|
|
38
|
+
error: 'Failed to list executions',
|
|
39
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* GET /api/executions/:runId
|
|
45
|
+
* Get details for a specific execution
|
|
46
|
+
*/
|
|
47
|
+
executionRoutes.get('/:runId', (req, res) => {
|
|
48
|
+
try {
|
|
49
|
+
const stateStore = getStateStore();
|
|
50
|
+
const runId = Array.isArray(req.params.runId) ? req.params.runId[0] : req.params.runId;
|
|
51
|
+
const execution = stateStore.getExecution(runId);
|
|
52
|
+
if (!execution) {
|
|
53
|
+
res.status(404).json({ error: 'Execution not found' });
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
res.json(execution);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('Error getting execution:', error);
|
|
60
|
+
res.status(500).json({
|
|
61
|
+
error: 'Failed to get execution',
|
|
62
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* GET /api/executions/:runId/checkpoints
|
|
68
|
+
* Get checkpoints for a specific execution
|
|
69
|
+
*/
|
|
70
|
+
executionRoutes.get('/:runId/checkpoints', (req, res) => {
|
|
71
|
+
try {
|
|
72
|
+
const stateStore = getStateStore();
|
|
73
|
+
const runId = Array.isArray(req.params.runId) ? req.params.runId[0] : req.params.runId;
|
|
74
|
+
const checkpoints = stateStore.getCheckpoints(runId);
|
|
75
|
+
res.json(checkpoints);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.error('Error getting checkpoints:', error);
|
|
79
|
+
res.status(500).json({
|
|
80
|
+
error: 'Failed to get checkpoints',
|
|
81
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
/**
|
|
86
|
+
* GET /api/executions/:runId/stats
|
|
87
|
+
* Get execution statistics
|
|
88
|
+
*/
|
|
89
|
+
executionRoutes.get('/:runId/stats', (req, res) => {
|
|
90
|
+
try {
|
|
91
|
+
const stateStore = getStateStore();
|
|
92
|
+
const runId = Array.isArray(req.params.runId) ? req.params.runId[0] : req.params.runId;
|
|
93
|
+
const execution = stateStore.getExecution(runId);
|
|
94
|
+
if (!execution) {
|
|
95
|
+
res.status(404).json({ error: 'Execution not found' });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const checkpoints = stateStore.getCheckpoints(runId);
|
|
99
|
+
const completedSteps = checkpoints.filter((c) => c.status === 'completed').length;
|
|
100
|
+
const failedSteps = checkpoints.filter((c) => c.status === 'failed').length;
|
|
101
|
+
const stats = {
|
|
102
|
+
runId,
|
|
103
|
+
workflowId: execution.workflowId,
|
|
104
|
+
status: execution.status,
|
|
105
|
+
totalSteps: execution.totalSteps,
|
|
106
|
+
completedSteps,
|
|
107
|
+
failedSteps,
|
|
108
|
+
currentStep: execution.currentStep,
|
|
109
|
+
duration: execution.completedAt && execution.startedAt
|
|
110
|
+
? execution.completedAt.getTime() - execution.startedAt.getTime()
|
|
111
|
+
: null,
|
|
112
|
+
startedAt: execution.startedAt,
|
|
113
|
+
completedAt: execution.completedAt,
|
|
114
|
+
};
|
|
115
|
+
res.json(stats);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error('Error getting execution stats:', error);
|
|
119
|
+
res.status(500).json({
|
|
120
|
+
error: 'Failed to get execution stats',
|
|
121
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=executions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executions.js","sourceRoot":"","sources":["../../../../src/server/routes/executions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,EAAE,CAAC;AAExC;;;GAGG;AACH,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACvD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;QAExD,4CAA4C;QAC5C,MAAM,SAAS,GAAG,CAAC,GAAY,EAAsB,EAAE;YACrD,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,GAAG,CAAC;YACxC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ;gBAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YACtF,OAAO,SAAS,CAAC;QACnB,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEnF,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,CAAC;YAC3C,UAAU,EAAE,aAAa;YACzB,MAAM,EAAE,SAAgB;YACxB,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QAClD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE,2BAA2B;YAClC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAClE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEH;;;GAGG;AACH,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IAC7D,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QAEvF,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACjD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE,yBAAyB;YAChC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAClE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEH;;;GAGG;AACH,eAAe,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QAEvF,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACrD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACnD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE,2BAA2B;YAClC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAClE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEH;;;GAGG;AACH,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACnE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QAEvF,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;QAClF,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QAE5E,MAAM,KAAK,GAAG;YACZ,KAAK;YACL,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,cAAc;YACd,WAAW;YACX,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,QAAQ,EACN,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,SAAS;gBAC1C,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE;gBACjE,CAAC,CAAC,IAAI;YACV,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,WAAW,EAAE,SAAS,CAAC,WAAW;SACnC,CAAC;QAEF,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACvD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE,+BAA+B;YACtC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAClE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form routes for human-in-the-loop workflows
|
|
3
|
+
*
|
|
4
|
+
* Handles form rendering and submission for workflows paused with wait steps.
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from 'express';
|
|
7
|
+
const router = Router();
|
|
8
|
+
// ExecutionManager instance (set via setExecutionManager)
|
|
9
|
+
let executionManager = null;
|
|
10
|
+
/**
|
|
11
|
+
* Set the ExecutionManager instance (called from server/index.ts)
|
|
12
|
+
*/
|
|
13
|
+
export function setExecutionManager(manager) {
|
|
14
|
+
executionManager = manager;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* GET /form/:runId/:stepId/:token
|
|
18
|
+
* Retrieve form schema and render form page
|
|
19
|
+
*/
|
|
20
|
+
router.get('/:runId/:stepId/:token', async (req, res) => {
|
|
21
|
+
try {
|
|
22
|
+
const runId = String(req.params.runId);
|
|
23
|
+
const stepId = String(req.params.stepId);
|
|
24
|
+
const token = String(req.params.token);
|
|
25
|
+
if (!executionManager) {
|
|
26
|
+
res.status(503).json({
|
|
27
|
+
error: 'Service unavailable',
|
|
28
|
+
message: 'ExecutionManager not initialized',
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Get execution status to verify it's waiting
|
|
33
|
+
const status = executionManager.getExecutionStatus(runId);
|
|
34
|
+
if (!status) {
|
|
35
|
+
res.status(404).json({
|
|
36
|
+
error: 'Not found',
|
|
37
|
+
message: `Execution ${runId} not found`,
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (status.status !== 'running') {
|
|
42
|
+
res.status(400).json({
|
|
43
|
+
error: 'Invalid state',
|
|
44
|
+
message: `Execution is not running (status: ${status.status})`,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Find the step that's waiting for form input
|
|
49
|
+
const waitingStep = status.stepResults.find(sr => sr.stepId === stepId && sr.status === 'completed');
|
|
50
|
+
if (!waitingStep || !waitingStep.output) {
|
|
51
|
+
res.status(404).json({
|
|
52
|
+
error: 'Not found',
|
|
53
|
+
message: `No waiting step found for ${stepId}`,
|
|
54
|
+
});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const stepOutput = waitingStep.output;
|
|
58
|
+
// Verify token matches
|
|
59
|
+
if (stepOutput.resumeToken !== token) {
|
|
60
|
+
res.status(403).json({
|
|
61
|
+
error: 'Forbidden',
|
|
62
|
+
message: 'Invalid resume token',
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Verify mode is form
|
|
67
|
+
if (stepOutput.mode !== 'form') {
|
|
68
|
+
res.status(400).json({
|
|
69
|
+
error: 'Invalid mode',
|
|
70
|
+
message: `Step is not in form mode (mode: ${stepOutput.mode})`,
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Return form schema
|
|
75
|
+
res.json({
|
|
76
|
+
runId,
|
|
77
|
+
stepId,
|
|
78
|
+
workflowId: status.workflowId,
|
|
79
|
+
workflowPath: status.workflowPath,
|
|
80
|
+
fields: stepOutput.fields || {},
|
|
81
|
+
submitUrl: `/api/form/${runId}/${stepId}/${token}`,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
res.status(500).json({
|
|
86
|
+
error: 'Failed to get form',
|
|
87
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
/**
|
|
92
|
+
* POST /form/:runId/:stepId/:token
|
|
93
|
+
* Submit form data and resume workflow execution
|
|
94
|
+
*/
|
|
95
|
+
router.post('/:runId/:stepId/:token', async (req, res) => {
|
|
96
|
+
try {
|
|
97
|
+
const runId = String(req.params.runId);
|
|
98
|
+
const stepId = String(req.params.stepId);
|
|
99
|
+
const token = String(req.params.token);
|
|
100
|
+
const formData = req.body;
|
|
101
|
+
if (!executionManager) {
|
|
102
|
+
res.status(503).json({
|
|
103
|
+
error: 'Service unavailable',
|
|
104
|
+
message: 'ExecutionManager not initialized',
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Verify execution exists and is waiting
|
|
109
|
+
const status = executionManager.getExecutionStatus(runId);
|
|
110
|
+
if (!status) {
|
|
111
|
+
res.status(404).json({
|
|
112
|
+
error: 'Not found',
|
|
113
|
+
message: `Execution ${runId} not found`,
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (status.status !== 'running') {
|
|
118
|
+
res.status(400).json({
|
|
119
|
+
error: 'Invalid state',
|
|
120
|
+
message: `Execution is not running (status: ${status.status})`,
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Find the waiting step
|
|
125
|
+
const waitingStep = status.stepResults.find(sr => sr.stepId === stepId && sr.status === 'completed');
|
|
126
|
+
if (!waitingStep || !waitingStep.output) {
|
|
127
|
+
res.status(404).json({
|
|
128
|
+
error: 'Not found',
|
|
129
|
+
message: `No waiting step found for ${stepId}`,
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const stepOutput = waitingStep.output;
|
|
134
|
+
// Verify token
|
|
135
|
+
if (stepOutput.resumeToken !== token) {
|
|
136
|
+
res.status(403).json({
|
|
137
|
+
error: 'Forbidden',
|
|
138
|
+
message: 'Invalid resume token',
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// TODO: Validate form data against field schema
|
|
143
|
+
// Resume execution with form data
|
|
144
|
+
await executionManager.resumeExecution(runId, stepId, formData);
|
|
145
|
+
res.json({
|
|
146
|
+
success: true,
|
|
147
|
+
runId,
|
|
148
|
+
stepId,
|
|
149
|
+
message: 'Form submitted successfully. Workflow execution resumed.',
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
res.status(500).json({
|
|
154
|
+
error: 'Failed to submit form',
|
|
155
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
export { router as formRoutes };
|
|
160
|
+
//# sourceMappingURL=form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../../../src/server/routes/form.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { DEFAULT_SETTINGS, deepMergeSettings, } from '../../shared/settings.js';
|
|
7
|
+
let settingsDir = join(homedir(), '.marktoflow');
|
|
8
|
+
/**
|
|
9
|
+
* Override the settings directory (used for testing).
|
|
10
|
+
*/
|
|
11
|
+
export function setSettingsDir(dir) {
|
|
12
|
+
settingsDir = dir;
|
|
13
|
+
}
|
|
14
|
+
function getSettingsFile() {
|
|
15
|
+
return join(settingsDir, 'settings.json');
|
|
16
|
+
}
|
|
17
|
+
async function ensureSettingsDir() {
|
|
18
|
+
if (!existsSync(settingsDir)) {
|
|
19
|
+
await mkdir(settingsDir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function readSettings() {
|
|
23
|
+
await ensureSettingsDir();
|
|
24
|
+
try {
|
|
25
|
+
const raw = await readFile(getSettingsFile(), 'utf-8');
|
|
26
|
+
const saved = JSON.parse(raw);
|
|
27
|
+
return deepMergeSettings(DEFAULT_SETTINGS, saved);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// File doesn't exist or is invalid — write defaults and return them
|
|
31
|
+
await writeFile(getSettingsFile(), JSON.stringify(DEFAULT_SETTINGS, null, 2));
|
|
32
|
+
return { ...DEFAULT_SETTINGS };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function writeSettings(settings) {
|
|
36
|
+
await ensureSettingsDir();
|
|
37
|
+
await writeFile(getSettingsFile(), JSON.stringify(settings, null, 2));
|
|
38
|
+
}
|
|
39
|
+
const router = Router();
|
|
40
|
+
// GET /api/settings — return full settings (merged with defaults)
|
|
41
|
+
router.get('/', async (_req, res) => {
|
|
42
|
+
try {
|
|
43
|
+
const settings = await readSettings();
|
|
44
|
+
res.json(settings);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
res.status(500).json({
|
|
48
|
+
error: 'Failed to read settings',
|
|
49
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// PUT /api/settings — full replace (used for reset-all)
|
|
54
|
+
router.put('/', async (req, res) => {
|
|
55
|
+
try {
|
|
56
|
+
const settings = deepMergeSettings(DEFAULT_SETTINGS, req.body);
|
|
57
|
+
await writeSettings(settings);
|
|
58
|
+
res.json(settings);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
res.status(500).json({
|
|
62
|
+
error: 'Failed to write settings',
|
|
63
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// PATCH /api/settings/:category — partial update of one category
|
|
68
|
+
router.patch('/:category', async (req, res) => {
|
|
69
|
+
try {
|
|
70
|
+
const category = req.params.category;
|
|
71
|
+
if (!(category in DEFAULT_SETTINGS)) {
|
|
72
|
+
return res.status(400).json({ error: `Unknown settings category: ${category}` });
|
|
73
|
+
}
|
|
74
|
+
const settings = await readSettings();
|
|
75
|
+
const current = settings[category];
|
|
76
|
+
const merged = { ...current, ...req.body };
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
+
settings[category] = merged;
|
|
79
|
+
await writeSettings(settings);
|
|
80
|
+
res.json(settings);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
res.status(500).json({
|
|
84
|
+
error: 'Failed to update settings',
|
|
85
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
export { router as settingsRoutes };
|
|
90
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../../src/server/routes/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { readdir, readFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
export const templateRoutes = Router();
|
|
5
|
+
let cachedTemplates = null;
|
|
6
|
+
// Get template list (seeded from examples/)
|
|
7
|
+
templateRoutes.get('/', async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
if (cachedTemplates) {
|
|
10
|
+
res.json({ templates: filterTemplates(cachedTemplates, req.query) });
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const examplesDir = join(process.cwd(), 'examples');
|
|
14
|
+
const templates = [];
|
|
15
|
+
try {
|
|
16
|
+
const dirs = await readdir(examplesDir, { withFileTypes: true });
|
|
17
|
+
for (const dir of dirs) {
|
|
18
|
+
if (!dir.isDirectory())
|
|
19
|
+
continue;
|
|
20
|
+
const workflowPath = join(examplesDir, dir.name, 'workflow.md');
|
|
21
|
+
try {
|
|
22
|
+
const content = await readFile(workflowPath, 'utf-8');
|
|
23
|
+
const name = dir.name.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
24
|
+
// Extract description from frontmatter
|
|
25
|
+
const descMatch = content.match(/description:\s*['""]?(.+?)['""]?\s*$/m);
|
|
26
|
+
const tagsMatch = content.match(/tags:\s*\[([^\]]+)\]/);
|
|
27
|
+
const tags = tagsMatch ? tagsMatch[1].split(',').map((t) => t.trim().replace(/['"]/g, '')) : [];
|
|
28
|
+
templates.push({
|
|
29
|
+
id: dir.name,
|
|
30
|
+
name,
|
|
31
|
+
description: descMatch?.[1] || `${name} workflow template`,
|
|
32
|
+
category: inferCategory(dir.name, tags),
|
|
33
|
+
tags,
|
|
34
|
+
path: workflowPath,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Skip directories without workflow.md
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// examples dir doesn't exist
|
|
44
|
+
}
|
|
45
|
+
// Add built-in templates
|
|
46
|
+
templates.push({ id: 'blank', name: 'Blank Workflow', description: 'Start from scratch', category: 'basic', tags: ['starter'], path: '' }, { id: 'api-integration', name: 'API Integration', description: 'Connect to any REST API', category: 'integration', tags: ['http', 'api'], path: '' }, { id: 'data-pipeline', name: 'Data Pipeline', description: 'ETL workflow with transform steps', category: 'data', tags: ['transform', 'etl'], path: '' });
|
|
47
|
+
cachedTemplates = templates;
|
|
48
|
+
res.json({ templates: filterTemplates(templates, req.query) });
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
res.status(500).json({
|
|
52
|
+
error: 'Failed to list templates',
|
|
53
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
// Get template content
|
|
58
|
+
templateRoutes.get('/:id', async (req, res) => {
|
|
59
|
+
try {
|
|
60
|
+
const templates = cachedTemplates || [];
|
|
61
|
+
const template = templates.find((t) => t.id === req.params.id);
|
|
62
|
+
if (!template) {
|
|
63
|
+
res.status(404).json({ error: 'Template not found' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
let content = '';
|
|
67
|
+
if (template.path) {
|
|
68
|
+
content = await readFile(template.path, 'utf-8');
|
|
69
|
+
}
|
|
70
|
+
res.json({ template, content });
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
res.status(500).json({
|
|
74
|
+
error: 'Failed to get template',
|
|
75
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
function inferCategory(name, tags) {
|
|
80
|
+
const all = [name, ...tags].join(' ').toLowerCase();
|
|
81
|
+
if (all.includes('review') || all.includes('pr'))
|
|
82
|
+
return 'development';
|
|
83
|
+
if (all.includes('slack') || all.includes('notification'))
|
|
84
|
+
return 'communication';
|
|
85
|
+
if (all.includes('incident') || all.includes('pager'))
|
|
86
|
+
return 'operations';
|
|
87
|
+
if (all.includes('sprint') || all.includes('standup'))
|
|
88
|
+
return 'agile';
|
|
89
|
+
if (all.includes('data') || all.includes('etl'))
|
|
90
|
+
return 'data';
|
|
91
|
+
return 'general';
|
|
92
|
+
}
|
|
93
|
+
function filterTemplates(templates, query) {
|
|
94
|
+
let filtered = templates;
|
|
95
|
+
if (query.category) {
|
|
96
|
+
filtered = filtered.filter((t) => t.category === query.category);
|
|
97
|
+
}
|
|
98
|
+
if (query.search) {
|
|
99
|
+
const search = query.search.toLowerCase();
|
|
100
|
+
filtered = filtered.filter((t) => t.name.toLowerCase().includes(search) ||
|
|
101
|
+
t.description.toLowerCase().includes(search) ||
|
|
102
|
+
t.tags.some((tag) => tag.toLowerCase().includes(search)));
|
|
103
|
+
}
|
|
104
|
+
return filtered;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../../src/server/routes/templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { VersionService } from '../services/VersionService.js';
|
|
3
|
+
export const versionRoutes = Router();
|
|
4
|
+
// List versions for a workflow
|
|
5
|
+
versionRoutes.get('/:path(*)/versions', (req, res) => {
|
|
6
|
+
try {
|
|
7
|
+
const workflowPath = req.params.path;
|
|
8
|
+
const versions = VersionService.listVersions(workflowPath);
|
|
9
|
+
res.json({ versions });
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
res.status(500).json({
|
|
13
|
+
error: 'Failed to list versions',
|
|
14
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
// Create a version snapshot
|
|
19
|
+
versionRoutes.post('/:path(*)/versions', (req, res) => {
|
|
20
|
+
try {
|
|
21
|
+
const workflowPath = req.params.path;
|
|
22
|
+
const { content, message, author, isAutoSave } = req.body;
|
|
23
|
+
if (!content) {
|
|
24
|
+
res.status(400).json({ error: 'Content is required' });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const version = VersionService.createVersion(workflowPath, content, message, author, isAutoSave);
|
|
28
|
+
res.json({ version });
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
res.status(500).json({
|
|
32
|
+
error: 'Failed to create version',
|
|
33
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// Get a specific version
|
|
38
|
+
versionRoutes.get('/:path(*)/versions/:versionId', (req, res) => {
|
|
39
|
+
try {
|
|
40
|
+
const workflowPath = req.params.path;
|
|
41
|
+
const versionId = req.params.versionId;
|
|
42
|
+
const version = VersionService.getVersion(workflowPath, versionId);
|
|
43
|
+
if (!version) {
|
|
44
|
+
res.status(404).json({ error: 'Version not found' });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
res.json({ version });
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
res.status(500).json({
|
|
51
|
+
error: 'Failed to get version',
|
|
52
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Restore a version
|
|
57
|
+
versionRoutes.post('/:path(*)/versions/:versionId/restore', (req, res) => {
|
|
58
|
+
try {
|
|
59
|
+
const workflowPath = req.params.path;
|
|
60
|
+
const versionId = req.params.versionId;
|
|
61
|
+
const version = VersionService.getVersion(workflowPath, versionId);
|
|
62
|
+
if (!version) {
|
|
63
|
+
res.status(404).json({ error: 'Version not found' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Create a new version that restores this content
|
|
67
|
+
const restored = VersionService.createVersion(workflowPath, version.content, `Restored from version ${version.version}`, req.body.author || 'system');
|
|
68
|
+
res.json({ version: restored, restoredContent: version.content });
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
res.status(500).json({
|
|
72
|
+
error: 'Failed to restore version',
|
|
73
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// Compare two versions
|
|
78
|
+
versionRoutes.get('/:path(*)/versions/compare', (req, res) => {
|
|
79
|
+
try {
|
|
80
|
+
const workflowPath = req.params.path;
|
|
81
|
+
const v1 = req.query.v1;
|
|
82
|
+
const v2 = req.query.v2;
|
|
83
|
+
if (!v1 || !v2) {
|
|
84
|
+
res.status(400).json({ error: 'v1 and v2 query parameters are required' });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const diff = VersionService.compareVersions(workflowPath, v1, v2);
|
|
88
|
+
if (!diff) {
|
|
89
|
+
res.status(404).json({ error: 'One or both versions not found' });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
res.json({ diff });
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
res.status(500).json({
|
|
96
|
+
error: 'Failed to compare versions',
|
|
97
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=versions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../../../../src/server/routes/versions.ts"],"names":[],"mappings":"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"}
|