@genfeedai/workflow-ui 0.1.3 → 0.1.4

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