@genfeedai/workflow-ui 0.1.0
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/dist/canvas.d.mts +27 -0
- package/dist/canvas.d.ts +27 -0
- package/dist/canvas.js +45 -0
- package/dist/canvas.mjs +16 -0
- package/dist/chunk-22PDGHNQ.mjs +737 -0
- package/dist/chunk-3SPPKCWR.js +458 -0
- package/dist/chunk-3YFFDHC5.js +300 -0
- package/dist/chunk-5HJFQVUR.js +61 -0
- package/dist/chunk-5LQ4QBR5.js +2 -0
- package/dist/chunk-6DOEUDD5.js +254 -0
- package/dist/chunk-7SKSRSS7.mjs +57 -0
- package/dist/chunk-AC6TWLRT.mjs +27 -0
- package/dist/chunk-ADWNF7V3.js +120 -0
- package/dist/chunk-BJ3R5R32.mjs +2163 -0
- package/dist/chunk-CETJJ73S.js +1555 -0
- package/dist/chunk-CSUBLSKZ.mjs +1002 -0
- package/dist/chunk-CV4M7CNU.mjs +251 -0
- package/dist/chunk-E323WAZG.mjs +272 -0
- package/dist/chunk-E544XUBL.js +378 -0
- package/dist/chunk-EC2ZIWOK.js +1007 -0
- package/dist/chunk-EFXQT23N.mjs +99 -0
- package/dist/chunk-EMUMKW5C.js +107 -0
- package/dist/chunk-FOMOOERN.js +2 -0
- package/dist/chunk-FT33LFII.mjs +21 -0
- package/dist/chunk-FT64PCUP.mjs +533 -0
- package/dist/chunk-H6LZKSLY.js +5678 -0
- package/dist/chunk-HPQT36RR.js +543 -0
- package/dist/chunk-JLWKW3G5.js +2 -0
- package/dist/chunk-L5TF4EHW.mjs +1 -0
- package/dist/chunk-LAJ34AH2.mjs +374 -0
- package/dist/chunk-LDN7IX4Y.mjs +1 -0
- package/dist/chunk-MLJJBBTB.mjs +1 -0
- package/dist/chunk-NSDLGLAQ.js +2166 -0
- package/dist/chunk-RJ262NXS.js +24 -0
- package/dist/chunk-RXNEDWK2.js +141 -0
- package/dist/chunk-SW7QNEZU.js +744 -0
- package/dist/chunk-UQQUWGHW.mjs +118 -0
- package/dist/chunk-VOGL2WCE.mjs +1542 -0
- package/dist/chunk-VRN3UWE5.mjs +138 -0
- package/dist/chunk-XV5Z5XYR.mjs +5640 -0
- package/dist/chunk-Z7PWFZG5.js +30 -0
- package/dist/chunk-ZJD5WMR3.mjs +418 -0
- package/dist/hooks.d.mts +255 -0
- package/dist/hooks.d.ts +255 -0
- package/dist/hooks.js +56 -0
- package/dist/hooks.mjs +11 -0
- package/dist/index.d.mts +29 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +180 -0
- package/dist/index.mjs +19 -0
- package/dist/lib.d.mts +164 -0
- package/dist/lib.d.ts +164 -0
- package/dist/lib.js +144 -0
- package/dist/lib.mjs +3 -0
- package/dist/nodes.d.mts +128 -0
- package/dist/nodes.d.ts +128 -0
- package/dist/nodes.js +151 -0
- package/dist/nodes.mjs +14 -0
- package/dist/panels.d.mts +22 -0
- package/dist/panels.d.ts +22 -0
- package/dist/panels.js +21 -0
- package/dist/panels.mjs +4 -0
- package/dist/promptLibraryStore-BZnfmEkc.d.ts +464 -0
- package/dist/promptLibraryStore-zqb59nsu.d.mts +464 -0
- package/dist/provider.d.mts +29 -0
- package/dist/provider.d.ts +29 -0
- package/dist/provider.js +17 -0
- package/dist/provider.mjs +4 -0
- package/dist/stores.d.mts +96 -0
- package/dist/stores.d.ts +96 -0
- package/dist/stores.js +113 -0
- package/dist/stores.mjs +43 -0
- package/dist/toolbar.d.mts +73 -0
- package/dist/toolbar.d.ts +73 -0
- package/dist/toolbar.js +34 -0
- package/dist/toolbar.mjs +5 -0
- package/dist/types-ipAnBzAJ.d.mts +46 -0
- package/dist/types-ipAnBzAJ.d.ts +46 -0
- package/dist/ui.d.mts +67 -0
- package/dist/ui.d.ts +67 -0
- package/dist/ui.js +84 -0
- package/dist/ui.mjs +3 -0
- package/dist/workflowStore-4EGKJLYK.mjs +3 -0
- package/dist/workflowStore-KM32FDL7.js +12 -0
- package/package.json +117 -0
- package/src/styles/workflow-ui.css +186 -0
|
@@ -0,0 +1,1007 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkNSDLGLAQ_js = require('./chunk-NSDLGLAQ.js');
|
|
4
|
+
var chunkZ7PWFZG5_js = require('./chunk-Z7PWFZG5.js');
|
|
5
|
+
var zustand = require('zustand');
|
|
6
|
+
|
|
7
|
+
var notificationId = 0;
|
|
8
|
+
var useUIStore = zustand.create((set) => ({
|
|
9
|
+
showPalette: true,
|
|
10
|
+
showMinimap: true,
|
|
11
|
+
showAIGenerator: false,
|
|
12
|
+
showDebugPanel: false,
|
|
13
|
+
selectedNodeId: null,
|
|
14
|
+
selectedEdgeId: null,
|
|
15
|
+
highlightedNodeIds: [],
|
|
16
|
+
activeModal: null,
|
|
17
|
+
nodeDetailNodeId: null,
|
|
18
|
+
nodeDetailActiveTab: "preview",
|
|
19
|
+
nodeDetailStartIndex: 0,
|
|
20
|
+
notifications: [],
|
|
21
|
+
togglePalette: () => {
|
|
22
|
+
set((state) => ({ showPalette: !state.showPalette }));
|
|
23
|
+
},
|
|
24
|
+
toggleMinimap: () => {
|
|
25
|
+
set((state) => ({ showMinimap: !state.showMinimap }));
|
|
26
|
+
},
|
|
27
|
+
toggleAIGenerator: () => {
|
|
28
|
+
set((state) => ({ showAIGenerator: !state.showAIGenerator }));
|
|
29
|
+
},
|
|
30
|
+
toggleDebugPanel: () => {
|
|
31
|
+
set((state) => ({ showDebugPanel: !state.showDebugPanel }));
|
|
32
|
+
},
|
|
33
|
+
setShowDebugPanel: (show) => {
|
|
34
|
+
set({ showDebugPanel: show });
|
|
35
|
+
},
|
|
36
|
+
selectNode: (nodeId) => {
|
|
37
|
+
set({ selectedNodeId: nodeId, selectedEdgeId: null });
|
|
38
|
+
},
|
|
39
|
+
selectEdge: (edgeId) => {
|
|
40
|
+
set({ selectedEdgeId: edgeId, selectedNodeId: null });
|
|
41
|
+
},
|
|
42
|
+
setHighlightedNodeIds: (ids) => {
|
|
43
|
+
set({ highlightedNodeIds: ids });
|
|
44
|
+
},
|
|
45
|
+
openModal: (modal) => {
|
|
46
|
+
set({ activeModal: modal });
|
|
47
|
+
},
|
|
48
|
+
closeModal: () => {
|
|
49
|
+
set({ activeModal: null });
|
|
50
|
+
},
|
|
51
|
+
openNodeDetailModal: (nodeId, tab = "preview", startIndex = 0) => {
|
|
52
|
+
set({
|
|
53
|
+
activeModal: "nodeDetail",
|
|
54
|
+
nodeDetailNodeId: nodeId,
|
|
55
|
+
nodeDetailActiveTab: tab,
|
|
56
|
+
nodeDetailStartIndex: startIndex
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
closeNodeDetailModal: () => {
|
|
60
|
+
set({
|
|
61
|
+
activeModal: null,
|
|
62
|
+
nodeDetailNodeId: null,
|
|
63
|
+
nodeDetailActiveTab: "preview",
|
|
64
|
+
nodeDetailStartIndex: 0
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
setNodeDetailTab: (tab) => {
|
|
68
|
+
set({ nodeDetailActiveTab: tab });
|
|
69
|
+
},
|
|
70
|
+
addNotification: (notification) => {
|
|
71
|
+
const id = `notification-${++notificationId}`;
|
|
72
|
+
set((state) => ({
|
|
73
|
+
notifications: [...state.notifications, { ...notification, id }]
|
|
74
|
+
}));
|
|
75
|
+
if (notification.duration !== 0) {
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
set((state) => ({
|
|
78
|
+
notifications: state.notifications.filter((n) => n.id !== id)
|
|
79
|
+
}));
|
|
80
|
+
}, notification.duration ?? 5e3);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
removeNotification: (id) => {
|
|
84
|
+
set((state) => ({
|
|
85
|
+
notifications: state.notifications.filter((n) => n.id !== id)
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
// src/stores/settingsStore.ts
|
|
91
|
+
var import_types = chunkZ7PWFZG5_js.__toESM(chunkNSDLGLAQ_js.require_dist());
|
|
92
|
+
var STORAGE_KEY = "genfeed-settings";
|
|
93
|
+
var MAX_RECENT_MODELS = 8;
|
|
94
|
+
var DEFAULT_SETTINGS = {
|
|
95
|
+
providers: {
|
|
96
|
+
replicate: { apiKey: null, enabled: true },
|
|
97
|
+
fal: { apiKey: null, enabled: false },
|
|
98
|
+
huggingface: { apiKey: null, enabled: false },
|
|
99
|
+
"genfeed-ai": { apiKey: null, enabled: true }
|
|
100
|
+
},
|
|
101
|
+
defaults: {
|
|
102
|
+
imageModel: "nano-banana-pro",
|
|
103
|
+
imageProvider: "replicate",
|
|
104
|
+
videoModel: "veo-3.1",
|
|
105
|
+
videoProvider: "replicate"
|
|
106
|
+
},
|
|
107
|
+
edgeStyle: "default",
|
|
108
|
+
showMinimap: true,
|
|
109
|
+
autoSaveEnabled: true,
|
|
110
|
+
recentModels: [],
|
|
111
|
+
hasSeenWelcome: false,
|
|
112
|
+
debugMode: false
|
|
113
|
+
};
|
|
114
|
+
function loadFromStorage() {
|
|
115
|
+
if (typeof window === "undefined") return {};
|
|
116
|
+
try {
|
|
117
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
118
|
+
if (stored) {
|
|
119
|
+
const parsed = JSON.parse(stored);
|
|
120
|
+
return {
|
|
121
|
+
providers: { ...DEFAULT_SETTINGS.providers, ...parsed.providers },
|
|
122
|
+
defaults: { ...DEFAULT_SETTINGS.defaults, ...parsed.defaults },
|
|
123
|
+
edgeStyle: parsed.edgeStyle === "bezier" ? "default" : parsed.edgeStyle ?? DEFAULT_SETTINGS.edgeStyle,
|
|
124
|
+
showMinimap: parsed.showMinimap ?? DEFAULT_SETTINGS.showMinimap,
|
|
125
|
+
autoSaveEnabled: parsed.autoSaveEnabled ?? true,
|
|
126
|
+
recentModels: parsed.recentModels ?? [],
|
|
127
|
+
hasSeenWelcome: parsed.hasSeenWelcome ?? false,
|
|
128
|
+
debugMode: parsed.debugMode ?? false
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
return {};
|
|
134
|
+
}
|
|
135
|
+
function saveToStorage(state) {
|
|
136
|
+
if (typeof window === "undefined") return;
|
|
137
|
+
try {
|
|
138
|
+
const toSave = {
|
|
139
|
+
providers: {
|
|
140
|
+
replicate: {
|
|
141
|
+
apiKey: state.providers.replicate.apiKey,
|
|
142
|
+
enabled: state.providers.replicate.enabled
|
|
143
|
+
},
|
|
144
|
+
fal: {
|
|
145
|
+
apiKey: state.providers.fal.apiKey,
|
|
146
|
+
enabled: state.providers.fal.enabled
|
|
147
|
+
},
|
|
148
|
+
huggingface: {
|
|
149
|
+
apiKey: state.providers.huggingface.apiKey,
|
|
150
|
+
enabled: state.providers.huggingface.enabled
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
defaults: state.defaults,
|
|
154
|
+
edgeStyle: state.edgeStyle,
|
|
155
|
+
showMinimap: state.showMinimap,
|
|
156
|
+
autoSaveEnabled: state.autoSaveEnabled,
|
|
157
|
+
recentModels: state.recentModels.slice(0, MAX_RECENT_MODELS),
|
|
158
|
+
hasSeenWelcome: state.hasSeenWelcome,
|
|
159
|
+
debugMode: state.debugMode
|
|
160
|
+
};
|
|
161
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(toSave));
|
|
162
|
+
} catch {
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
var initialState = { ...DEFAULT_SETTINGS, ...loadFromStorage() };
|
|
166
|
+
var useSettingsStore = zustand.create((set, get) => {
|
|
167
|
+
const setAndPersist = (updater) => {
|
|
168
|
+
set((state) => {
|
|
169
|
+
const newState = updater(state);
|
|
170
|
+
saveToStorage({ ...state, ...newState });
|
|
171
|
+
return newState;
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
providers: initialState.providers,
|
|
176
|
+
defaults: initialState.defaults,
|
|
177
|
+
edgeStyle: initialState.edgeStyle,
|
|
178
|
+
showMinimap: initialState.showMinimap,
|
|
179
|
+
autoSaveEnabled: initialState.autoSaveEnabled,
|
|
180
|
+
recentModels: initialState.recentModels,
|
|
181
|
+
hasSeenWelcome: initialState.hasSeenWelcome,
|
|
182
|
+
debugMode: initialState.debugMode,
|
|
183
|
+
toggleAutoSave: () => {
|
|
184
|
+
setAndPersist((state) => ({ autoSaveEnabled: !state.autoSaveEnabled }));
|
|
185
|
+
},
|
|
186
|
+
setProviderKey: (provider, key) => {
|
|
187
|
+
setAndPersist((state) => ({
|
|
188
|
+
providers: {
|
|
189
|
+
...state.providers,
|
|
190
|
+
[provider]: {
|
|
191
|
+
...state.providers[provider],
|
|
192
|
+
apiKey: key,
|
|
193
|
+
enabled: key ? true : state.providers[provider].enabled
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}));
|
|
197
|
+
},
|
|
198
|
+
setProviderEnabled: (provider, enabled) => {
|
|
199
|
+
setAndPersist((state) => ({
|
|
200
|
+
providers: {
|
|
201
|
+
...state.providers,
|
|
202
|
+
[provider]: {
|
|
203
|
+
...state.providers[provider],
|
|
204
|
+
enabled
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}));
|
|
208
|
+
},
|
|
209
|
+
setDefaultModel: (type, model, provider) => {
|
|
210
|
+
setAndPersist((state) => ({
|
|
211
|
+
defaults: {
|
|
212
|
+
...state.defaults,
|
|
213
|
+
...type === "image" ? { imageModel: model, imageProvider: provider } : { videoModel: model, videoProvider: provider }
|
|
214
|
+
}
|
|
215
|
+
}));
|
|
216
|
+
},
|
|
217
|
+
setEdgeStyle: (style) => {
|
|
218
|
+
setAndPersist(() => ({ edgeStyle: style }));
|
|
219
|
+
import('./workflowStore-KM32FDL7.js').then(({ useWorkflowStore: useWorkflowStore2 }) => {
|
|
220
|
+
useWorkflowStore2.getState().setEdgeStyle(style);
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
setShowMinimap: (show) => {
|
|
224
|
+
setAndPersist(() => ({ showMinimap: show }));
|
|
225
|
+
},
|
|
226
|
+
addRecentModel: (model) => {
|
|
227
|
+
setAndPersist((state) => {
|
|
228
|
+
const filtered = state.recentModels.filter(
|
|
229
|
+
(m) => !(m.id === model.id && m.provider === model.provider)
|
|
230
|
+
);
|
|
231
|
+
const newRecentModels = [{ ...model, timestamp: Date.now() }, ...filtered].slice(
|
|
232
|
+
0,
|
|
233
|
+
MAX_RECENT_MODELS
|
|
234
|
+
);
|
|
235
|
+
return { recentModels: newRecentModels };
|
|
236
|
+
});
|
|
237
|
+
},
|
|
238
|
+
clearProviderKey: (provider) => {
|
|
239
|
+
setAndPersist((state) => ({
|
|
240
|
+
providers: {
|
|
241
|
+
...state.providers,
|
|
242
|
+
[provider]: {
|
|
243
|
+
...state.providers[provider],
|
|
244
|
+
apiKey: null
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}));
|
|
248
|
+
},
|
|
249
|
+
clearAllKeys: () => {
|
|
250
|
+
setAndPersist((state) => ({
|
|
251
|
+
providers: {
|
|
252
|
+
replicate: { ...state.providers.replicate, apiKey: null },
|
|
253
|
+
fal: { ...state.providers.fal, apiKey: null },
|
|
254
|
+
huggingface: { ...state.providers.huggingface, apiKey: null },
|
|
255
|
+
"genfeed-ai": { ...state.providers["genfeed-ai"], apiKey: null }
|
|
256
|
+
}
|
|
257
|
+
}));
|
|
258
|
+
},
|
|
259
|
+
setHasSeenWelcome: (seen) => {
|
|
260
|
+
setAndPersist(() => ({ hasSeenWelcome: seen }));
|
|
261
|
+
},
|
|
262
|
+
setDebugMode: (enabled) => {
|
|
263
|
+
setAndPersist(() => ({ debugMode: enabled }));
|
|
264
|
+
},
|
|
265
|
+
isProviderConfigured: (provider) => {
|
|
266
|
+
const state = get();
|
|
267
|
+
return !!state.providers[provider].apiKey;
|
|
268
|
+
},
|
|
269
|
+
getProviderHeader: (provider) => {
|
|
270
|
+
const state = get();
|
|
271
|
+
const key = state.providers[provider].apiKey;
|
|
272
|
+
if (!key) return {};
|
|
273
|
+
const headerMap = {
|
|
274
|
+
[import_types.ProviderTypeEnum.REPLICATE]: "X-Replicate-Key",
|
|
275
|
+
[import_types.ProviderTypeEnum.FAL]: "X-Fal-Key",
|
|
276
|
+
[import_types.ProviderTypeEnum.HUGGINGFACE]: "X-HF-Key",
|
|
277
|
+
[import_types.ProviderTypeEnum.GENFEED_AI]: "X-Genfeed-Key"
|
|
278
|
+
};
|
|
279
|
+
return { [headerMap[provider]]: key };
|
|
280
|
+
},
|
|
281
|
+
// API Sync - stubbed as no-ops (consuming app provides real implementations)
|
|
282
|
+
isSyncing: false,
|
|
283
|
+
syncFromServer: async () => {
|
|
284
|
+
},
|
|
285
|
+
syncToServer: async () => {
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
var PROVIDER_INFO = {
|
|
290
|
+
[import_types.ProviderTypeEnum.REPLICATE]: {
|
|
291
|
+
name: "Replicate",
|
|
292
|
+
description: "Access thousands of open-source AI models",
|
|
293
|
+
docsUrl: "https://replicate.com/docs"
|
|
294
|
+
},
|
|
295
|
+
[import_types.ProviderTypeEnum.FAL]: {
|
|
296
|
+
name: "fal.ai",
|
|
297
|
+
description: "Fast inference for image and video generation",
|
|
298
|
+
docsUrl: "https://fal.ai/docs"
|
|
299
|
+
},
|
|
300
|
+
[import_types.ProviderTypeEnum.HUGGINGFACE]: {
|
|
301
|
+
name: "Hugging Face",
|
|
302
|
+
description: "The AI community platform with 500k+ models",
|
|
303
|
+
docsUrl: "https://huggingface.co/docs/api-inference"
|
|
304
|
+
},
|
|
305
|
+
[import_types.ProviderTypeEnum.GENFEED_AI]: {
|
|
306
|
+
name: "Genfeed AI",
|
|
307
|
+
description: "Built-in models powered by Genfeed",
|
|
308
|
+
docsUrl: "https://genfeed.ai/docs"
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
// src/stores/execution/slices/executionSlice.ts
|
|
313
|
+
var import_types3 = chunkZ7PWFZG5_js.__toESM(chunkNSDLGLAQ_js.require_dist());
|
|
314
|
+
|
|
315
|
+
// src/stores/execution/helpers/sseSubscription.ts
|
|
316
|
+
var import_types2 = chunkZ7PWFZG5_js.__toESM(chunkNSDLGLAQ_js.require_dist());
|
|
317
|
+
|
|
318
|
+
// src/stores/execution/helpers/outputHelpers.ts
|
|
319
|
+
function extractOutputValue(output) {
|
|
320
|
+
if (!output) return null;
|
|
321
|
+
if (typeof output === "string") {
|
|
322
|
+
return output;
|
|
323
|
+
}
|
|
324
|
+
if (Array.isArray(output) && output.length > 0) {
|
|
325
|
+
const first = output[0];
|
|
326
|
+
if (typeof first === "string") return first;
|
|
327
|
+
if (first && typeof first === "object" && "url" in first) {
|
|
328
|
+
return String(first.url);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (typeof output === "object" && output !== null) {
|
|
332
|
+
const obj = output;
|
|
333
|
+
if ("url" in obj) return String(obj.url);
|
|
334
|
+
if ("image" in obj) return String(obj.image);
|
|
335
|
+
if ("video" in obj) return String(obj.video);
|
|
336
|
+
if ("audio" in obj) return String(obj.audio);
|
|
337
|
+
}
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
function extractAllOutputValues(output) {
|
|
341
|
+
if (!output) return [];
|
|
342
|
+
if (typeof output === "string") {
|
|
343
|
+
return [output];
|
|
344
|
+
}
|
|
345
|
+
if (Array.isArray(output)) {
|
|
346
|
+
return output.filter((item) => typeof item === "string");
|
|
347
|
+
}
|
|
348
|
+
if (typeof output === "object" && output !== null) {
|
|
349
|
+
const obj = output;
|
|
350
|
+
if ("images" in obj && Array.isArray(obj.images)) {
|
|
351
|
+
return obj.images.filter((item) => typeof item === "string");
|
|
352
|
+
}
|
|
353
|
+
if ("image" in obj && typeof obj.image === "string") {
|
|
354
|
+
return [obj.image];
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return [];
|
|
358
|
+
}
|
|
359
|
+
function getOutputUpdate(nodeId, output, workflowStore) {
|
|
360
|
+
const node = workflowStore.getNodeById(nodeId);
|
|
361
|
+
if (!node) return {};
|
|
362
|
+
const nodeType = node.type;
|
|
363
|
+
const outputValue = extractOutputValue(output);
|
|
364
|
+
if (["imageGen"].includes(nodeType)) {
|
|
365
|
+
const allImages = extractAllOutputValues(output);
|
|
366
|
+
return {
|
|
367
|
+
outputImage: allImages[0] ?? null,
|
|
368
|
+
outputImages: allImages
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
if (["reframe", "upscale"].includes(nodeType)) {
|
|
372
|
+
const inputType = node.data.inputType;
|
|
373
|
+
if (inputType === "video") {
|
|
374
|
+
return { outputVideo: outputValue };
|
|
375
|
+
}
|
|
376
|
+
return { outputImage: outputValue };
|
|
377
|
+
}
|
|
378
|
+
if (["videoGen", "animation", "videoStitch", "lipSync", "voiceChange", "motionControl"].includes(
|
|
379
|
+
nodeType
|
|
380
|
+
)) {
|
|
381
|
+
return { outputVideo: outputValue };
|
|
382
|
+
}
|
|
383
|
+
if (nodeType === "textToSpeech") {
|
|
384
|
+
return { outputAudio: outputValue };
|
|
385
|
+
}
|
|
386
|
+
if (nodeType === "llm") {
|
|
387
|
+
const textOutput = Array.isArray(output) ? output.join("") : outputValue;
|
|
388
|
+
return { outputText: textOutput };
|
|
389
|
+
}
|
|
390
|
+
if (nodeType === "resize") {
|
|
391
|
+
return { outputMedia: outputValue };
|
|
392
|
+
}
|
|
393
|
+
return { output: outputValue };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// src/stores/execution/helpers/sseSubscription.ts
|
|
397
|
+
var API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://local.genfeed.ai:3001/api";
|
|
398
|
+
var statusMap = {
|
|
399
|
+
pending: import_types2.NodeStatusEnum.IDLE,
|
|
400
|
+
processing: import_types2.NodeStatusEnum.PROCESSING,
|
|
401
|
+
complete: import_types2.NodeStatusEnum.COMPLETE,
|
|
402
|
+
succeeded: import_types2.NodeStatusEnum.COMPLETE,
|
|
403
|
+
error: import_types2.NodeStatusEnum.ERROR
|
|
404
|
+
};
|
|
405
|
+
function applyJobUpdates(jobs, workflowStore, debugMode, set, filterNodeId) {
|
|
406
|
+
if (!jobs || jobs.length === 0) return;
|
|
407
|
+
set((state) => {
|
|
408
|
+
let didChange = false;
|
|
409
|
+
const newJobs = new Map(state.jobs);
|
|
410
|
+
const newDebugPayloads = [];
|
|
411
|
+
for (const job of jobs) {
|
|
412
|
+
if (filterNodeId && job.nodeId !== filterNodeId) continue;
|
|
413
|
+
const status = job.status;
|
|
414
|
+
const output = job.output ?? null;
|
|
415
|
+
const error = job.error ?? null;
|
|
416
|
+
const existing = state.jobs.get(job.predictionId);
|
|
417
|
+
if (!existing) {
|
|
418
|
+
didChange = true;
|
|
419
|
+
newJobs.set(job.predictionId, {
|
|
420
|
+
nodeId: job.nodeId,
|
|
421
|
+
predictionId: job.predictionId,
|
|
422
|
+
status,
|
|
423
|
+
progress: 0,
|
|
424
|
+
output,
|
|
425
|
+
error,
|
|
426
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
427
|
+
});
|
|
428
|
+
} else if (existing.status !== status || existing.output !== output || existing.error !== error) {
|
|
429
|
+
didChange = true;
|
|
430
|
+
newJobs.set(job.predictionId, {
|
|
431
|
+
...existing,
|
|
432
|
+
status,
|
|
433
|
+
output,
|
|
434
|
+
error
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
if (job.result?.debugPayload) {
|
|
438
|
+
const node = workflowStore.getNodeById(job.nodeId);
|
|
439
|
+
newDebugPayloads.push({
|
|
440
|
+
nodeId: job.nodeId,
|
|
441
|
+
nodeName: String(node?.data?.label || node?.data?.name || job.nodeId),
|
|
442
|
+
nodeType: node?.type || "unknown",
|
|
443
|
+
model: job.result.debugPayload.model,
|
|
444
|
+
input: job.result.debugPayload.input,
|
|
445
|
+
timestamp: job.result.debugPayload.timestamp
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (!didChange && newDebugPayloads.length === 0) return state;
|
|
450
|
+
if (newDebugPayloads.length > 0 && debugMode) {
|
|
451
|
+
useUIStore.getState().setShowDebugPanel(true);
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
jobs: didChange ? newJobs : state.jobs,
|
|
455
|
+
debugPayloads: newDebugPayloads.length > 0 ? [
|
|
456
|
+
...state.debugPayloads.filter(
|
|
457
|
+
(existing) => !newDebugPayloads.some((newP) => newP.nodeId === existing.nodeId)
|
|
458
|
+
),
|
|
459
|
+
...newDebugPayloads
|
|
460
|
+
] : state.debugPayloads
|
|
461
|
+
};
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
async function reconcileNodeStatuses(executionId) {
|
|
465
|
+
try {
|
|
466
|
+
const response = await fetch(`${API_BASE_URL}/executions/${executionId}`);
|
|
467
|
+
if (!response.ok) return;
|
|
468
|
+
const execution = await response.json();
|
|
469
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
470
|
+
for (const nodeResult of execution.nodeResults || []) {
|
|
471
|
+
const nodeStatus = statusMap[nodeResult.status] ?? import_types2.NodeStatusEnum.IDLE;
|
|
472
|
+
const isSuccess = nodeResult.status === "complete" || nodeResult.status === "succeeded";
|
|
473
|
+
workflowStore.updateNodeData(nodeResult.nodeId, {
|
|
474
|
+
status: nodeStatus,
|
|
475
|
+
error: isSuccess ? void 0 : nodeResult.error,
|
|
476
|
+
...nodeResult.output && getOutputUpdate(nodeResult.nodeId, nodeResult.output, workflowStore)
|
|
477
|
+
});
|
|
478
|
+
if (isSuccess && nodeResult.output) {
|
|
479
|
+
workflowStore.propagateOutputsDownstream(nodeResult.nodeId);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
} catch {
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
function createExecutionSubscription(executionId, set) {
|
|
486
|
+
const eventSource = new EventSource(`${API_BASE_URL}/executions/${executionId}/stream`);
|
|
487
|
+
const propagatedNodeIds = /* @__PURE__ */ new Set();
|
|
488
|
+
set({ eventSource });
|
|
489
|
+
eventSource.onmessage = (event) => {
|
|
490
|
+
void (async () => {
|
|
491
|
+
try {
|
|
492
|
+
const data = JSON.parse(event.data);
|
|
493
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
494
|
+
const nodeResults = data.nodeResults || [];
|
|
495
|
+
for (const nodeResult of nodeResults) {
|
|
496
|
+
const nodeStatus = statusMap[nodeResult.status] ?? import_types2.NodeStatusEnum.IDLE;
|
|
497
|
+
const isSuccess = nodeResult.status === "complete" || nodeResult.status === "succeeded";
|
|
498
|
+
workflowStore.updateNodeData(nodeResult.nodeId, {
|
|
499
|
+
status: nodeStatus,
|
|
500
|
+
error: isSuccess ? void 0 : nodeResult.error,
|
|
501
|
+
...nodeResult.output && getOutputUpdate(nodeResult.nodeId, nodeResult.output, workflowStore)
|
|
502
|
+
});
|
|
503
|
+
if ((nodeResult.status === "complete" || nodeResult.status === "succeeded") && nodeResult.output && !propagatedNodeIds.has(nodeResult.nodeId)) {
|
|
504
|
+
propagatedNodeIds.add(nodeResult.nodeId);
|
|
505
|
+
workflowStore.propagateOutputsDownstream(nodeResult.nodeId);
|
|
506
|
+
}
|
|
507
|
+
if (nodeResult.status === "error") {
|
|
508
|
+
set({ lastFailedNodeId: nodeResult.nodeId });
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
applyJobUpdates(data.jobs, workflowStore, data.debugMode, set);
|
|
512
|
+
const isComplete = ["completed", "failed", "cancelled", "error"].includes(data.status);
|
|
513
|
+
const hasFailedNode = (data.nodeResults || []).some((r) => r.status === "error");
|
|
514
|
+
const hasPendingNodes = (data.pendingNodes || []).length > 0;
|
|
515
|
+
const hasProcessingNodes = (data.nodeResults || []).some((r) => r.status === "processing");
|
|
516
|
+
const isDone = isComplete || hasFailedNode && !hasPendingNodes && !hasProcessingNodes;
|
|
517
|
+
if (isDone) {
|
|
518
|
+
propagatedNodeIds.clear();
|
|
519
|
+
eventSource.close();
|
|
520
|
+
await reconcileNodeStatuses(executionId);
|
|
521
|
+
set({ isRunning: false, eventSource: null, currentNodeId: null, jobs: /* @__PURE__ */ new Map() });
|
|
522
|
+
if (data.status === "failed" || hasFailedNode) {
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
} catch {
|
|
526
|
+
}
|
|
527
|
+
})();
|
|
528
|
+
};
|
|
529
|
+
eventSource.onerror = () => {
|
|
530
|
+
eventSource.close();
|
|
531
|
+
void reconcileNodeStatuses(executionId).then(() => {
|
|
532
|
+
set({ isRunning: false, eventSource: null });
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
return eventSource;
|
|
536
|
+
}
|
|
537
|
+
function createNodeExecutionSubscription(executionId, nodeId, set, _get) {
|
|
538
|
+
const eventSource = new EventSource(`${API_BASE_URL}/executions/${executionId}/stream`);
|
|
539
|
+
const propagatedNodeIds = /* @__PURE__ */ new Set();
|
|
540
|
+
eventSource.onmessage = (event) => {
|
|
541
|
+
void (async () => {
|
|
542
|
+
try {
|
|
543
|
+
const data = JSON.parse(event.data);
|
|
544
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
545
|
+
const nodeResults = data.nodeResults || [];
|
|
546
|
+
for (const nodeResult of nodeResults) {
|
|
547
|
+
const nodeStatus = statusMap[nodeResult.status] ?? import_types2.NodeStatusEnum.IDLE;
|
|
548
|
+
const isSuccess = nodeResult.status === "complete" || nodeResult.status === "succeeded";
|
|
549
|
+
workflowStore.updateNodeData(nodeResult.nodeId, {
|
|
550
|
+
status: nodeStatus,
|
|
551
|
+
error: isSuccess ? void 0 : nodeResult.error,
|
|
552
|
+
...nodeResult.output && getOutputUpdate(nodeResult.nodeId, nodeResult.output, workflowStore)
|
|
553
|
+
});
|
|
554
|
+
if ((nodeResult.status === "complete" || nodeResult.status === "succeeded") && nodeResult.output && !propagatedNodeIds.has(nodeResult.nodeId)) {
|
|
555
|
+
propagatedNodeIds.add(nodeResult.nodeId);
|
|
556
|
+
workflowStore.propagateOutputsDownstream(nodeResult.nodeId);
|
|
557
|
+
}
|
|
558
|
+
if (nodeResult.status === "error") {
|
|
559
|
+
set({ lastFailedNodeId: nodeResult.nodeId });
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
applyJobUpdates(data.jobs, workflowStore, data.debugMode, set, nodeId);
|
|
563
|
+
const isComplete = ["completed", "failed", "cancelled", "error"].includes(data.status);
|
|
564
|
+
const hasFailedNode = (data.nodeResults || []).some((r) => r.status === "error");
|
|
565
|
+
const hasPendingNodes = (data.pendingNodes || []).length > 0;
|
|
566
|
+
const hasProcessingNodes = (data.nodeResults || []).some((r) => r.status === "processing");
|
|
567
|
+
const isDone = isComplete || hasFailedNode && !hasPendingNodes && !hasProcessingNodes;
|
|
568
|
+
if (isDone) {
|
|
569
|
+
propagatedNodeIds.clear();
|
|
570
|
+
eventSource.close();
|
|
571
|
+
await reconcileNodeStatuses(executionId);
|
|
572
|
+
set((state) => {
|
|
573
|
+
const newMap = new Map(state.activeNodeExecutions);
|
|
574
|
+
newMap.delete(nodeId);
|
|
575
|
+
return { activeNodeExecutions: newMap };
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
} catch {
|
|
579
|
+
}
|
|
580
|
+
})();
|
|
581
|
+
};
|
|
582
|
+
eventSource.onerror = () => {
|
|
583
|
+
eventSource.close();
|
|
584
|
+
void reconcileNodeStatuses(executionId).then(() => {
|
|
585
|
+
set((state) => {
|
|
586
|
+
const newMap = new Map(state.activeNodeExecutions);
|
|
587
|
+
newMap.delete(nodeId);
|
|
588
|
+
return { activeNodeExecutions: newMap };
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
return eventSource;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// src/stores/execution/slices/executionSlice.ts
|
|
596
|
+
var API_BASE_URL2 = process.env.NEXT_PUBLIC_API_URL || "http://local.genfeed.ai:3001/api";
|
|
597
|
+
async function apiPost(path, body) {
|
|
598
|
+
const response = await fetch(`${API_BASE_URL2}${path}`, {
|
|
599
|
+
method: "POST",
|
|
600
|
+
headers: { "Content-Type": "application/json" },
|
|
601
|
+
...body && { body: JSON.stringify(body) }
|
|
602
|
+
});
|
|
603
|
+
if (!response.ok) {
|
|
604
|
+
const errorData = await response.json().catch(() => ({}));
|
|
605
|
+
throw new Error(errorData.message || `API error: ${response.status}`);
|
|
606
|
+
}
|
|
607
|
+
return response.json();
|
|
608
|
+
}
|
|
609
|
+
var createExecutionSlice = (set, get) => ({
|
|
610
|
+
executeWorkflow: async () => {
|
|
611
|
+
const { isRunning, resetExecution } = get();
|
|
612
|
+
if (isRunning) return;
|
|
613
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
614
|
+
const debugMode = useSettingsStore.getState().debugMode;
|
|
615
|
+
const validation = workflowStore.validateWorkflow();
|
|
616
|
+
if (!validation.isValid) {
|
|
617
|
+
set({ validationErrors: validation });
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
set({ validationErrors: null });
|
|
621
|
+
resetExecution();
|
|
622
|
+
if (debugMode) {
|
|
623
|
+
useUIStore.getState().setShowDebugPanel(true);
|
|
624
|
+
}
|
|
625
|
+
if (workflowStore.isDirty || !workflowStore.workflowId) {
|
|
626
|
+
try {
|
|
627
|
+
await workflowStore.saveWorkflow();
|
|
628
|
+
} catch {
|
|
629
|
+
set({
|
|
630
|
+
validationErrors: {
|
|
631
|
+
isValid: false,
|
|
632
|
+
errors: [{ nodeId: "", message: "Failed to save workflow", severity: "error" }],
|
|
633
|
+
warnings: []
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
const workflowId = workflowStore.workflowId;
|
|
640
|
+
if (!workflowId) {
|
|
641
|
+
set({
|
|
642
|
+
validationErrors: {
|
|
643
|
+
isValid: false,
|
|
644
|
+
errors: [{ nodeId: "", message: "Workflow must be saved first", severity: "error" }],
|
|
645
|
+
warnings: []
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
set({ isRunning: true });
|
|
651
|
+
for (const node of workflowStore.nodes) {
|
|
652
|
+
workflowStore.updateNodeData(node.id, {
|
|
653
|
+
status: import_types3.NodeStatusEnum.IDLE,
|
|
654
|
+
error: void 0,
|
|
655
|
+
progress: void 0
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
try {
|
|
659
|
+
const execution = await apiPost(`/workflows/${workflowId}/execute`, {
|
|
660
|
+
debugMode
|
|
661
|
+
});
|
|
662
|
+
const executionId = execution._id;
|
|
663
|
+
set({ executionId });
|
|
664
|
+
createExecutionSubscription(executionId, set);
|
|
665
|
+
} catch (error) {
|
|
666
|
+
set({
|
|
667
|
+
isRunning: false,
|
|
668
|
+
validationErrors: {
|
|
669
|
+
isValid: false,
|
|
670
|
+
errors: [
|
|
671
|
+
{
|
|
672
|
+
nodeId: "",
|
|
673
|
+
message: error instanceof Error ? error.message : "Execution failed",
|
|
674
|
+
severity: "error"
|
|
675
|
+
}
|
|
676
|
+
],
|
|
677
|
+
warnings: []
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
},
|
|
682
|
+
executeNode: async (nodeId) => {
|
|
683
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
684
|
+
const debugMode = useSettingsStore.getState().debugMode;
|
|
685
|
+
if (workflowStore.isDirty || !workflowStore.workflowId) {
|
|
686
|
+
try {
|
|
687
|
+
await workflowStore.saveWorkflow();
|
|
688
|
+
} catch {
|
|
689
|
+
workflowStore.updateNodeData(nodeId, {
|
|
690
|
+
status: import_types3.NodeStatusEnum.ERROR,
|
|
691
|
+
error: "Failed to save workflow"
|
|
692
|
+
});
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
const workflowId = workflowStore.workflowId;
|
|
697
|
+
if (!workflowId) {
|
|
698
|
+
workflowStore.updateNodeData(nodeId, {
|
|
699
|
+
status: import_types3.NodeStatusEnum.ERROR,
|
|
700
|
+
error: "Workflow must be saved first"
|
|
701
|
+
});
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
if (debugMode) {
|
|
705
|
+
useUIStore.getState().setShowDebugPanel(true);
|
|
706
|
+
}
|
|
707
|
+
try {
|
|
708
|
+
const execution = await apiPost(`/workflows/${workflowId}/execute`, {
|
|
709
|
+
debugMode,
|
|
710
|
+
selectedNodeIds: [nodeId]
|
|
711
|
+
});
|
|
712
|
+
const executionId = execution._id;
|
|
713
|
+
const eventSource = createNodeExecutionSubscription(executionId, nodeId, set, get);
|
|
714
|
+
const nodeExecution = {
|
|
715
|
+
executionId,
|
|
716
|
+
nodeIds: [nodeId],
|
|
717
|
+
eventSource
|
|
718
|
+
};
|
|
719
|
+
set((state) => {
|
|
720
|
+
const newMap = new Map(state.activeNodeExecutions);
|
|
721
|
+
newMap.set(nodeId, nodeExecution);
|
|
722
|
+
return { activeNodeExecutions: newMap };
|
|
723
|
+
});
|
|
724
|
+
} catch (error) {
|
|
725
|
+
workflowStore.updateNodeData(nodeId, {
|
|
726
|
+
status: import_types3.NodeStatusEnum.ERROR,
|
|
727
|
+
error: error instanceof Error ? error.message : "Node execution failed"
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
executeSelectedNodes: async () => {
|
|
732
|
+
const { isRunning, resetExecution } = get();
|
|
733
|
+
if (isRunning) return;
|
|
734
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
735
|
+
const debugMode = useSettingsStore.getState().debugMode;
|
|
736
|
+
const { selectedNodeIds } = workflowStore;
|
|
737
|
+
if (selectedNodeIds.length === 0) {
|
|
738
|
+
set({
|
|
739
|
+
validationErrors: {
|
|
740
|
+
isValid: false,
|
|
741
|
+
errors: [{ nodeId: "", message: "No nodes selected", severity: "error" }],
|
|
742
|
+
warnings: []
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
set({ validationErrors: null });
|
|
748
|
+
resetExecution();
|
|
749
|
+
if (workflowStore.isDirty || !workflowStore.workflowId) {
|
|
750
|
+
try {
|
|
751
|
+
await workflowStore.saveWorkflow();
|
|
752
|
+
} catch {
|
|
753
|
+
set({
|
|
754
|
+
validationErrors: {
|
|
755
|
+
isValid: false,
|
|
756
|
+
errors: [{ nodeId: "", message: "Failed to save workflow", severity: "error" }],
|
|
757
|
+
warnings: []
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
const workflowId = workflowStore.workflowId;
|
|
764
|
+
if (!workflowId) {
|
|
765
|
+
set({
|
|
766
|
+
validationErrors: {
|
|
767
|
+
isValid: false,
|
|
768
|
+
errors: [{ nodeId: "", message: "Workflow must be saved first", severity: "error" }],
|
|
769
|
+
warnings: []
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
set({ isRunning: true, executingNodeIds: selectedNodeIds });
|
|
775
|
+
if (debugMode) {
|
|
776
|
+
useUIStore.getState().setShowDebugPanel(true);
|
|
777
|
+
}
|
|
778
|
+
for (const nodeId of selectedNodeIds) {
|
|
779
|
+
workflowStore.updateNodeData(nodeId, {
|
|
780
|
+
status: import_types3.NodeStatusEnum.IDLE,
|
|
781
|
+
error: void 0,
|
|
782
|
+
progress: void 0
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
try {
|
|
786
|
+
const execution = await apiPost(`/workflows/${workflowId}/execute`, {
|
|
787
|
+
debugMode,
|
|
788
|
+
selectedNodeIds
|
|
789
|
+
});
|
|
790
|
+
const executionId = execution._id;
|
|
791
|
+
set({ executionId });
|
|
792
|
+
createExecutionSubscription(executionId, set);
|
|
793
|
+
} catch (error) {
|
|
794
|
+
set({
|
|
795
|
+
isRunning: false,
|
|
796
|
+
validationErrors: {
|
|
797
|
+
isValid: false,
|
|
798
|
+
errors: [
|
|
799
|
+
{
|
|
800
|
+
nodeId: "",
|
|
801
|
+
message: error instanceof Error ? error.message : "Partial execution failed",
|
|
802
|
+
severity: "error"
|
|
803
|
+
}
|
|
804
|
+
],
|
|
805
|
+
warnings: []
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
},
|
|
810
|
+
resumeFromFailed: async () => {
|
|
811
|
+
const { isRunning, executionId, lastFailedNodeId } = get();
|
|
812
|
+
if (isRunning || !executionId || !lastFailedNodeId) return;
|
|
813
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
814
|
+
const debugMode = useSettingsStore.getState().debugMode;
|
|
815
|
+
const workflowId = workflowStore.workflowId;
|
|
816
|
+
if (!workflowId) {
|
|
817
|
+
set({
|
|
818
|
+
validationErrors: {
|
|
819
|
+
isValid: false,
|
|
820
|
+
errors: [{ nodeId: "", message: "Workflow must be saved first", severity: "error" }],
|
|
821
|
+
warnings: []
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
set({ isRunning: true, validationErrors: null });
|
|
827
|
+
if (debugMode) {
|
|
828
|
+
useUIStore.getState().setShowDebugPanel(true);
|
|
829
|
+
}
|
|
830
|
+
workflowStore.updateNodeData(lastFailedNodeId, {
|
|
831
|
+
status: import_types3.NodeStatusEnum.IDLE,
|
|
832
|
+
error: void 0,
|
|
833
|
+
progress: void 0
|
|
834
|
+
});
|
|
835
|
+
try {
|
|
836
|
+
const execution = await apiPost(`/workflows/${workflowId}/execute`, {
|
|
837
|
+
debugMode
|
|
838
|
+
});
|
|
839
|
+
const newExecutionId = execution._id;
|
|
840
|
+
set({ executionId: newExecutionId, lastFailedNodeId: null });
|
|
841
|
+
createExecutionSubscription(newExecutionId, set);
|
|
842
|
+
} catch (error) {
|
|
843
|
+
set({
|
|
844
|
+
isRunning: false,
|
|
845
|
+
validationErrors: {
|
|
846
|
+
isValid: false,
|
|
847
|
+
errors: [
|
|
848
|
+
{
|
|
849
|
+
nodeId: "",
|
|
850
|
+
message: error instanceof Error ? error.message : "Resume failed",
|
|
851
|
+
severity: "error"
|
|
852
|
+
}
|
|
853
|
+
],
|
|
854
|
+
warnings: []
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
},
|
|
859
|
+
stopExecution: () => {
|
|
860
|
+
const { eventSource, executionId } = get();
|
|
861
|
+
if (eventSource) {
|
|
862
|
+
eventSource.close();
|
|
863
|
+
}
|
|
864
|
+
if (executionId) {
|
|
865
|
+
apiPost(`/executions/${executionId}/stop`).catch(() => {
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
set({
|
|
869
|
+
isRunning: false,
|
|
870
|
+
eventSource: null,
|
|
871
|
+
currentNodeId: null
|
|
872
|
+
});
|
|
873
|
+
},
|
|
874
|
+
stopNodeExecution: (nodeId) => {
|
|
875
|
+
const { activeNodeExecutions } = get();
|
|
876
|
+
const nodeExecution = activeNodeExecutions.get(nodeId);
|
|
877
|
+
if (nodeExecution) {
|
|
878
|
+
nodeExecution.eventSource.close();
|
|
879
|
+
apiPost(`/executions/${nodeExecution.executionId}/stop`).catch(() => {
|
|
880
|
+
});
|
|
881
|
+
set((state) => {
|
|
882
|
+
const newMap = new Map(state.activeNodeExecutions);
|
|
883
|
+
newMap.delete(nodeId);
|
|
884
|
+
return { activeNodeExecutions: newMap };
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
888
|
+
workflowStore.updateNodeData(nodeId, { status: import_types3.NodeStatusEnum.IDLE, error: void 0 });
|
|
889
|
+
},
|
|
890
|
+
isNodeExecuting: (nodeId) => {
|
|
891
|
+
const { activeNodeExecutions } = get();
|
|
892
|
+
return activeNodeExecutions.has(nodeId);
|
|
893
|
+
},
|
|
894
|
+
clearValidationErrors: () => {
|
|
895
|
+
set({ validationErrors: null });
|
|
896
|
+
},
|
|
897
|
+
resetExecution: () => {
|
|
898
|
+
const { eventSource, activeNodeExecutions } = get();
|
|
899
|
+
if (eventSource) {
|
|
900
|
+
eventSource.close();
|
|
901
|
+
}
|
|
902
|
+
for (const nodeExecution of activeNodeExecutions.values()) {
|
|
903
|
+
nodeExecution.eventSource.close();
|
|
904
|
+
}
|
|
905
|
+
set({
|
|
906
|
+
isRunning: false,
|
|
907
|
+
jobs: /* @__PURE__ */ new Map(),
|
|
908
|
+
executionId: null,
|
|
909
|
+
currentNodeId: null,
|
|
910
|
+
executingNodeIds: [],
|
|
911
|
+
eventSource: null,
|
|
912
|
+
actualCost: 0,
|
|
913
|
+
lastFailedNodeId: null,
|
|
914
|
+
debugPayloads: [],
|
|
915
|
+
activeNodeExecutions: /* @__PURE__ */ new Map()
|
|
916
|
+
});
|
|
917
|
+
const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
|
|
918
|
+
for (const node of workflowStore.nodes) {
|
|
919
|
+
workflowStore.updateNodeData(node.id, {
|
|
920
|
+
status: import_types3.NodeStatusEnum.IDLE,
|
|
921
|
+
error: void 0,
|
|
922
|
+
progress: void 0
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
},
|
|
926
|
+
canResumeFromFailed: () => {
|
|
927
|
+
const { executionId, lastFailedNodeId, isRunning } = get();
|
|
928
|
+
return !isRunning && Boolean(executionId) && Boolean(lastFailedNodeId);
|
|
929
|
+
},
|
|
930
|
+
setEstimatedCost: (cost) => {
|
|
931
|
+
set({ estimatedCost: cost });
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
// src/stores/execution/slices/jobSlice.ts
|
|
936
|
+
var createJobSlice = (set, get) => ({
|
|
937
|
+
addJob: (nodeId, predictionId) => {
|
|
938
|
+
set((state) => {
|
|
939
|
+
const newJobs = new Map(state.jobs);
|
|
940
|
+
newJobs.set(predictionId, {
|
|
941
|
+
nodeId,
|
|
942
|
+
predictionId,
|
|
943
|
+
status: "pending",
|
|
944
|
+
progress: 0,
|
|
945
|
+
output: null,
|
|
946
|
+
error: null,
|
|
947
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
948
|
+
});
|
|
949
|
+
return { jobs: newJobs };
|
|
950
|
+
});
|
|
951
|
+
},
|
|
952
|
+
updateJob: (predictionId, updates) => {
|
|
953
|
+
set((state) => {
|
|
954
|
+
const newJobs = new Map(state.jobs);
|
|
955
|
+
const job = newJobs.get(predictionId);
|
|
956
|
+
if (job) {
|
|
957
|
+
newJobs.set(predictionId, { ...job, ...updates });
|
|
958
|
+
}
|
|
959
|
+
return { jobs: newJobs };
|
|
960
|
+
});
|
|
961
|
+
},
|
|
962
|
+
getJobByNodeId: (nodeId) => {
|
|
963
|
+
const { jobs } = get();
|
|
964
|
+
for (const job of jobs.values()) {
|
|
965
|
+
if (job.nodeId === nodeId) return job;
|
|
966
|
+
}
|
|
967
|
+
return void 0;
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
// src/stores/execution/executionStore.ts
|
|
972
|
+
var useExecutionStore = zustand.create()((...args) => {
|
|
973
|
+
const [set] = args;
|
|
974
|
+
return {
|
|
975
|
+
// Initial state
|
|
976
|
+
isRunning: false,
|
|
977
|
+
executionId: null,
|
|
978
|
+
currentNodeId: null,
|
|
979
|
+
executingNodeIds: [],
|
|
980
|
+
validationErrors: null,
|
|
981
|
+
eventSource: null,
|
|
982
|
+
lastFailedNodeId: null,
|
|
983
|
+
pausedAtNodeId: null,
|
|
984
|
+
jobs: /* @__PURE__ */ new Map(),
|
|
985
|
+
estimatedCost: 0,
|
|
986
|
+
actualCost: 0,
|
|
987
|
+
debugPayloads: [],
|
|
988
|
+
activeNodeExecutions: /* @__PURE__ */ new Map(),
|
|
989
|
+
// Debug payload actions
|
|
990
|
+
addDebugPayload: (payload) => {
|
|
991
|
+
set((state) => ({
|
|
992
|
+
debugPayloads: [...state.debugPayloads, payload]
|
|
993
|
+
}));
|
|
994
|
+
},
|
|
995
|
+
clearDebugPayloads: () => {
|
|
996
|
+
set({ debugPayloads: [] });
|
|
997
|
+
},
|
|
998
|
+
// Compose slices
|
|
999
|
+
...createJobSlice(...args),
|
|
1000
|
+
...createExecutionSlice(...args)
|
|
1001
|
+
};
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
exports.PROVIDER_INFO = PROVIDER_INFO;
|
|
1005
|
+
exports.useExecutionStore = useExecutionStore;
|
|
1006
|
+
exports.useSettingsStore = useSettingsStore;
|
|
1007
|
+
exports.useUIStore = useUIStore;
|