@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.
- package/dist/canvas.d.mts +16 -2
- package/dist/canvas.mjs +10 -8
- package/dist/chunk-6PSJTBNV.mjs +638 -0
- package/dist/chunk-7H3WJJYS.mjs +52 -0
- package/dist/{chunk-HCXI63ME.mjs → chunk-AUQGOJOQ.mjs} +27 -4
- package/dist/{chunk-AOTUCJMA.mjs → chunk-GWBGK3KL.mjs} +2 -2
- package/dist/chunk-JTPADIUO.mjs +130 -0
- package/dist/{chunk-SQK4JDYY.mjs → chunk-LT3ZJJL6.mjs} +9 -2
- package/dist/{chunk-7P2JWDC7.mjs → chunk-O5II6BOJ.mjs} +1198 -254
- package/dist/{chunk-AUZR6REQ.mjs → chunk-OQREHJXK.mjs} +1 -1
- package/dist/chunk-OY7BRSGG.mjs +60 -0
- package/dist/{chunk-E3YBVMYZ.mjs → chunk-PANZDSP6.mjs} +274 -305
- package/dist/chunk-PCIWWD37.mjs +90 -0
- package/dist/{chunk-RIGVIEYB.mjs → chunk-R727OFBR.mjs} +11 -1
- package/dist/chunk-ZD2BADZO.mjs +1294 -0
- package/dist/contextMenuStore-DMg0hJQ1.d.mts +22 -0
- package/dist/hooks.d.mts +53 -244
- package/dist/hooks.mjs +6 -6
- package/dist/index.d.mts +11 -7
- package/dist/index.mjs +13 -11
- package/dist/lib.d.mts +250 -4
- package/dist/lib.mjs +562 -2
- package/dist/nodes.d.mts +3 -1
- package/dist/nodes.mjs +6 -6
- package/dist/panels.mjs +3 -4
- package/dist/{promptLibraryStore-zqb59nsu.d.mts → promptLibraryStore-Bgw5LzvD.d.mts} +33 -5
- package/dist/provider.d.mts +2 -2
- package/dist/provider.mjs +0 -1
- package/dist/stores.d.mts +4 -3
- package/dist/stores.mjs +3 -40
- package/dist/toolbar.d.mts +3 -1
- package/dist/toolbar.mjs +5 -4
- package/dist/{types-ipAnBzAJ.d.mts → types-CF6DPx0P.d.mts} +8 -3
- package/dist/ui.d.mts +1 -1
- package/dist/ui.mjs +0 -1
- package/dist/{hooks.d.ts → useCommentNavigation-NzJjkaj2.d.mts} +15 -2
- package/dist/workflowStore-UAAKOOIK.mjs +2 -0
- package/package.json +30 -24
- package/dist/canvas.d.ts +0 -27
- package/dist/canvas.js +0 -45
- package/dist/chunk-3SPPKCWR.js +0 -458
- package/dist/chunk-3TMV3K34.js +0 -534
- package/dist/chunk-3YFFDHC5.js +0 -300
- package/dist/chunk-4MZ62VMF.js +0 -37
- package/dist/chunk-5HJFQVUR.js +0 -61
- package/dist/chunk-5LQ4QBR5.js +0 -2
- package/dist/chunk-6DOEUDD5.js +0 -254
- package/dist/chunk-AXFOCPPP.js +0 -998
- package/dist/chunk-BMFRA6GK.js +0 -1546
- package/dist/chunk-E323WAZG.mjs +0 -272
- package/dist/chunk-ECD5J2BA.js +0 -6022
- package/dist/chunk-EMGXUNBL.js +0 -120
- package/dist/chunk-EMUMKW5C.js +0 -107
- package/dist/chunk-FOMOOERN.js +0 -2
- package/dist/chunk-IASLG6IA.mjs +0 -118
- package/dist/chunk-IHF35QZD.js +0 -1095
- package/dist/chunk-JLWKW3G5.js +0 -2
- package/dist/chunk-KDIWRSYV.js +0 -375
- package/dist/chunk-L5TF4EHW.mjs +0 -1
- package/dist/chunk-RJ262NXS.js +0 -24
- package/dist/chunk-RXNEDWK2.js +0 -141
- package/dist/chunk-SEV2DWKF.js +0 -744
- package/dist/chunk-ZJWP5KGZ.mjs +0 -33
- package/dist/hooks.js +0 -56
- package/dist/index.d.ts +0 -29
- package/dist/index.js +0 -180
- package/dist/lib.d.ts +0 -164
- package/dist/lib.js +0 -144
- package/dist/nodes.d.ts +0 -128
- package/dist/nodes.js +0 -151
- package/dist/panels.d.ts +0 -22
- package/dist/panels.js +0 -21
- package/dist/promptLibraryStore-BZnfmEkc.d.ts +0 -464
- package/dist/provider.d.ts +0 -29
- package/dist/provider.js +0 -17
- package/dist/stores.d.ts +0 -96
- package/dist/stores.js +0 -113
- package/dist/toolbar.d.ts +0 -73
- package/dist/toolbar.js +0 -34
- package/dist/types-ipAnBzAJ.d.ts +0 -46
- package/dist/ui.d.ts +0 -67
- package/dist/ui.js +0 -84
- package/dist/workflowStore-7SDJC4UR.mjs +0 -3
- package/dist/workflowStore-LNJQ5RZG.js +0 -12
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useWorkflowStore } from './chunk-R727OFBR.mjs';
|
|
2
|
+
import { useMemo, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
function useCommentNavigation(nodeId) {
|
|
5
|
+
const nodes = useWorkflowStore((state) => state.nodes);
|
|
6
|
+
const getNodesWithComments = useWorkflowStore((state) => state.getNodesWithComments);
|
|
7
|
+
const markCommentViewed = useWorkflowStore((state) => state.markCommentViewed);
|
|
8
|
+
const setNavigationTarget = useWorkflowStore((state) => state.setNavigationTarget);
|
|
9
|
+
const nodeComment = useMemo(() => {
|
|
10
|
+
const node = nodes.find((n) => n.id === nodeId);
|
|
11
|
+
const data = node?.data;
|
|
12
|
+
return data?.comment?.trim() || null;
|
|
13
|
+
}, [nodes, nodeId]);
|
|
14
|
+
const nodesWithComments = useMemo(() => {
|
|
15
|
+
return getNodesWithComments();
|
|
16
|
+
}, [getNodesWithComments]);
|
|
17
|
+
const currentIndex = useMemo(() => {
|
|
18
|
+
return nodesWithComments.findIndex((n) => n.id === nodeId);
|
|
19
|
+
}, [nodesWithComments, nodeId]);
|
|
20
|
+
const navigateTo = useCallback(
|
|
21
|
+
(targetIndex) => {
|
|
22
|
+
const targetNode = nodesWithComments[targetIndex];
|
|
23
|
+
if (targetNode) {
|
|
24
|
+
markCommentViewed(targetNode.id);
|
|
25
|
+
setNavigationTarget(targetNode.id);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
[nodesWithComments, markCommentViewed, setNavigationTarget]
|
|
29
|
+
);
|
|
30
|
+
const onPrevious = useCallback(() => {
|
|
31
|
+
if (nodesWithComments.length === 0) return;
|
|
32
|
+
const newIndex = currentIndex <= 0 ? nodesWithComments.length - 1 : currentIndex - 1;
|
|
33
|
+
navigateTo(newIndex);
|
|
34
|
+
}, [currentIndex, nodesWithComments.length, navigateTo]);
|
|
35
|
+
const onNext = useCallback(() => {
|
|
36
|
+
if (nodesWithComments.length === 0) return;
|
|
37
|
+
const newIndex = (currentIndex + 1) % nodesWithComments.length;
|
|
38
|
+
navigateTo(newIndex);
|
|
39
|
+
}, [currentIndex, nodesWithComments.length, navigateTo]);
|
|
40
|
+
if (!nodeComment || currentIndex === -1) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
currentIndex: currentIndex + 1,
|
|
45
|
+
// 1-based for display
|
|
46
|
+
totalCount: nodesWithComments.length,
|
|
47
|
+
onPrevious,
|
|
48
|
+
onNext
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { useCommentNavigation };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { calculateWorkflowCost, formatCost } from './chunk-JTPADIUO.mjs';
|
|
2
|
+
import { useSettingsStore, useExecutionStore, useUIStore } from './chunk-LT3ZJJL6.mjs';
|
|
3
|
+
import { useWorkflowStore } from './chunk-R727OFBR.mjs';
|
|
4
|
+
import { X, CloudOff, Loader2, Cloud, Check, ChevronDown, SaveAll, Save, FolderOpen, Bug, LayoutGrid, Undo2, Redo2, Settings, AlertCircle, Minus, Plus, Square, Play, ChevronUp, PlayCircle, RotateCcw, DollarSign, MoreVertical } from 'lucide-react';
|
|
4
5
|
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
5
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
7
|
|
|
@@ -682,6 +683,28 @@ function BottomBar() {
|
|
|
682
683
|
}
|
|
683
684
|
);
|
|
684
685
|
}
|
|
686
|
+
function CostIndicator() {
|
|
687
|
+
const nodes = useWorkflowStore((state) => state.nodes);
|
|
688
|
+
const isRunning = useExecutionStore((state) => state.isRunning);
|
|
689
|
+
const actualCost = useExecutionStore((state) => state.actualCost);
|
|
690
|
+
const { openModal } = useUIStore();
|
|
691
|
+
const breakdown = useMemo(() => calculateWorkflowCost(nodes), [nodes]);
|
|
692
|
+
const displayCost = isRunning && actualCost > 0 ? actualCost : breakdown.total;
|
|
693
|
+
if (breakdown.nodes.length === 0) return null;
|
|
694
|
+
return /* @__PURE__ */ jsxs(
|
|
695
|
+
"button",
|
|
696
|
+
{
|
|
697
|
+
onClick: () => openModal("cost"),
|
|
698
|
+
title: "View cost breakdown",
|
|
699
|
+
className: "flex items-center gap-1.5 rounded-md border border-[var(--border)] px-2 py-1 text-sm text-[var(--muted-foreground)] transition hover:bg-[var(--secondary)] hover:text-[var(--foreground)]",
|
|
700
|
+
children: [
|
|
701
|
+
/* @__PURE__ */ jsx(DollarSign, { className: "h-3.5 w-3.5" }),
|
|
702
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: formatCost(displayCost) }),
|
|
703
|
+
isRunning && actualCost > 0 && /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-green-500 animate-pulse" })
|
|
704
|
+
]
|
|
705
|
+
}
|
|
706
|
+
);
|
|
707
|
+
}
|
|
685
708
|
function OverflowMenu({ items }) {
|
|
686
709
|
const [isOpen, setIsOpen] = useState(false);
|
|
687
710
|
const menuRef = useRef(null);
|
|
@@ -734,4 +757,4 @@ function OverflowMenu({ items }) {
|
|
|
734
757
|
] });
|
|
735
758
|
}
|
|
736
759
|
|
|
737
|
-
export { BottomBar, OverflowMenu, SaveAsDialog, SaveIndicator, Toolbar, ToolbarDropdown };
|
|
760
|
+
export { BottomBar, CostIndicator, OverflowMenu, SaveAsDialog, SaveIndicator, Toolbar, ToolbarDropdown };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Button } from './chunk-7SKSRSS7.mjs';
|
|
2
2
|
import { extractEnumValues, supportsImageInput, validateRequiredSchemaFields, CONNECTION_FIELDS, getSchemaDefaults, getImageDimensions, getVideoMetadata } from './chunk-EFXQT23N.mjs';
|
|
3
|
-
import { useExecutionStore } from './chunk-
|
|
4
|
-
import { useWorkflowStore } from './chunk-
|
|
3
|
+
import { useExecutionStore } from './chunk-LT3ZJJL6.mjs';
|
|
4
|
+
import { useWorkflowStore } from './chunk-R727OFBR.mjs';
|
|
5
5
|
import { useWorkflowUIConfig } from './chunk-FT33LFII.mjs';
|
|
6
6
|
import { useMemo, useCallback, useRef, useEffect, useState } from 'react';
|
|
7
7
|
import { ChevronDown, Expand, Square, Play } from 'lucide-react';
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { PRICING, DEFAULT_VIDEO_DURATION, IMAGE_NODE_TYPES, VIDEO_NODE_TYPES, LUMA_NODE_TYPES, TOPAZ_NODE_TYPES } from './chunk-OY7BRSGG.mjs';
|
|
2
|
+
|
|
3
|
+
// src/lib/costCalculator.ts
|
|
4
|
+
function isNodeType(type, list) {
|
|
5
|
+
return list.includes(type);
|
|
6
|
+
}
|
|
7
|
+
function getDataField(data, key, fallback) {
|
|
8
|
+
return data[key] ?? fallback;
|
|
9
|
+
}
|
|
10
|
+
function calculateWorkflowCost(nodes) {
|
|
11
|
+
const estimates = [];
|
|
12
|
+
for (const node of nodes) {
|
|
13
|
+
const data = node.data;
|
|
14
|
+
const type = node.type ?? "";
|
|
15
|
+
const label = getDataField(data, "label", type);
|
|
16
|
+
if (isNodeType(type, IMAGE_NODE_TYPES)) {
|
|
17
|
+
const model = getDataField(data, "model", "nano-banana");
|
|
18
|
+
const resolution = getDataField(data, "resolution", "2K");
|
|
19
|
+
let cost = 0;
|
|
20
|
+
const priceEntry = PRICING[model];
|
|
21
|
+
if (typeof priceEntry === "number") {
|
|
22
|
+
cost = priceEntry;
|
|
23
|
+
} else if (priceEntry && typeof priceEntry === "object" && !Array.isArray(priceEntry)) {
|
|
24
|
+
cost = priceEntry[resolution] ?? Object.values(priceEntry)[0] ?? 0;
|
|
25
|
+
}
|
|
26
|
+
estimates.push({
|
|
27
|
+
nodeId: node.id,
|
|
28
|
+
nodeLabel: label,
|
|
29
|
+
nodeType: type,
|
|
30
|
+
model,
|
|
31
|
+
unit: "per image",
|
|
32
|
+
cost
|
|
33
|
+
});
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (isNodeType(type, VIDEO_NODE_TYPES)) {
|
|
37
|
+
const model = getDataField(data, "model", "veo-3.1-fast");
|
|
38
|
+
const duration = getDataField(data, "duration", DEFAULT_VIDEO_DURATION);
|
|
39
|
+
const generateAudio = getDataField(data, "generateAudio", true);
|
|
40
|
+
const priceEntry = PRICING[model];
|
|
41
|
+
let perSecond = 0;
|
|
42
|
+
if (priceEntry && typeof priceEntry === "object" && !Array.isArray(priceEntry)) {
|
|
43
|
+
const entry = priceEntry;
|
|
44
|
+
perSecond = generateAudio ? entry.withAudio ?? 0 : entry.withoutAudio ?? 0;
|
|
45
|
+
}
|
|
46
|
+
estimates.push({
|
|
47
|
+
nodeId: node.id,
|
|
48
|
+
nodeLabel: label,
|
|
49
|
+
nodeType: type,
|
|
50
|
+
model,
|
|
51
|
+
unit: `${duration}s video`,
|
|
52
|
+
cost: perSecond * duration
|
|
53
|
+
});
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (isNodeType(type, LUMA_NODE_TYPES)) {
|
|
57
|
+
const model = getDataField(data, "model", "photon-flash-1");
|
|
58
|
+
const inputType = getDataField(data, "inputType", "image");
|
|
59
|
+
let cost = 0;
|
|
60
|
+
if (inputType === "video") {
|
|
61
|
+
cost = PRICING["luma-reframe-video"] * DEFAULT_VIDEO_DURATION;
|
|
62
|
+
} else {
|
|
63
|
+
const imageEntry = PRICING["luma-reframe-image"];
|
|
64
|
+
cost = imageEntry[model] ?? 0.01;
|
|
65
|
+
}
|
|
66
|
+
estimates.push({
|
|
67
|
+
nodeId: node.id,
|
|
68
|
+
nodeLabel: label,
|
|
69
|
+
nodeType: type,
|
|
70
|
+
model,
|
|
71
|
+
unit: inputType === "video" ? "per video" : "per image",
|
|
72
|
+
cost
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (isNodeType(type, TOPAZ_NODE_TYPES)) {
|
|
77
|
+
const inputType = getDataField(data, "inputType", "image");
|
|
78
|
+
if (inputType === "video") {
|
|
79
|
+
const resolution = getDataField(data, "targetResolution", "1080p");
|
|
80
|
+
const fps = getDataField(data, "targetFps", 30);
|
|
81
|
+
const key = `${resolution}-${fps}`;
|
|
82
|
+
const pricePerChunk = PRICING["topaz-video-upscale"][key] ?? 0.101;
|
|
83
|
+
const duration = DEFAULT_VIDEO_DURATION;
|
|
84
|
+
const chunks = Math.ceil(duration / 5);
|
|
85
|
+
estimates.push({
|
|
86
|
+
nodeId: node.id,
|
|
87
|
+
nodeLabel: label,
|
|
88
|
+
nodeType: type,
|
|
89
|
+
model: "topaz-video",
|
|
90
|
+
unit: `${duration}s video`,
|
|
91
|
+
cost: pricePerChunk * chunks
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
const tier = PRICING["topaz-image-upscale"].find((t) => 1 <= t.maxMP) ?? PRICING["topaz-image-upscale"][0];
|
|
95
|
+
estimates.push({
|
|
96
|
+
nodeId: node.id,
|
|
97
|
+
nodeLabel: label,
|
|
98
|
+
nodeType: type,
|
|
99
|
+
model: getDataField(data, "model", "topaz-standard-v2"),
|
|
100
|
+
unit: "per image",
|
|
101
|
+
cost: tier.price
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (type === "llm") {
|
|
107
|
+
const maxTokens = getDataField(data, "maxTokens", 1024);
|
|
108
|
+
const estimatedTokens = maxTokens * 3;
|
|
109
|
+
estimates.push({
|
|
110
|
+
nodeId: node.id,
|
|
111
|
+
nodeLabel: label,
|
|
112
|
+
nodeType: type,
|
|
113
|
+
model: getDataField(data, "model", "llama"),
|
|
114
|
+
unit: `~${estimatedTokens} tokens`,
|
|
115
|
+
cost: estimatedTokens * PRICING.llama
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
total: estimates.reduce((sum, e) => sum + e.cost, 0),
|
|
121
|
+
nodes: estimates
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function formatCost(amount) {
|
|
125
|
+
if (amount === 0) return "$0.00";
|
|
126
|
+
if (amount < 0.01) return `$${amount.toFixed(4)}`;
|
|
127
|
+
return `$${amount.toFixed(2)}`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export { calculateWorkflowCost, formatCost };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useWorkflowStore } from './chunk-
|
|
1
|
+
import { useWorkflowStore } from './chunk-R727OFBR.mjs';
|
|
2
2
|
import { create } from 'zustand';
|
|
3
3
|
import { ProviderTypeEnum, NodeStatusEnum } from '@genfeedai/types';
|
|
4
4
|
|
|
@@ -12,6 +12,7 @@ var useUIStore = create((set) => ({
|
|
|
12
12
|
selectedEdgeId: null,
|
|
13
13
|
highlightedNodeIds: [],
|
|
14
14
|
activeModal: null,
|
|
15
|
+
connectionDropMenu: null,
|
|
15
16
|
nodeDetailNodeId: null,
|
|
16
17
|
nodeDetailActiveTab: "preview",
|
|
17
18
|
nodeDetailStartIndex: 0,
|
|
@@ -46,6 +47,12 @@ var useUIStore = create((set) => ({
|
|
|
46
47
|
closeModal: () => {
|
|
47
48
|
set({ activeModal: null });
|
|
48
49
|
},
|
|
50
|
+
openConnectionDropMenu: (params) => {
|
|
51
|
+
set({ connectionDropMenu: params });
|
|
52
|
+
},
|
|
53
|
+
closeConnectionDropMenu: () => {
|
|
54
|
+
set({ connectionDropMenu: null });
|
|
55
|
+
},
|
|
49
56
|
openNodeDetailModal: (nodeId, tab = "preview", startIndex = 0) => {
|
|
50
57
|
set({
|
|
51
58
|
activeModal: "nodeDetail",
|
|
@@ -211,7 +218,7 @@ var useSettingsStore = create((set, get) => {
|
|
|
211
218
|
},
|
|
212
219
|
setEdgeStyle: (style) => {
|
|
213
220
|
setAndPersist(() => ({ edgeStyle: style }));
|
|
214
|
-
import('./workflowStore-
|
|
221
|
+
import('./workflowStore-UAAKOOIK.mjs').then(({ useWorkflowStore: useWorkflowStore2 }) => {
|
|
215
222
|
useWorkflowStore2.getState().setEdgeStyle(style);
|
|
216
223
|
});
|
|
217
224
|
},
|