@genfeedai/workflow-ui 0.2.2 → 0.2.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/README.md +11 -33
- package/dist/canvas.d.ts +22 -22
- package/dist/canvas.mjs +16 -17
- package/dist/{chunk-WBR34V4L.mjs → chunk-2FUPL67V.mjs} +1593 -1045
- package/dist/{chunk-4VEN4UN7.mjs → chunk-53XDE62A.mjs} +818 -623
- package/dist/{chunk-PCIWWD37.mjs → chunk-7LV4UAUS.mjs} +19 -19
- package/dist/{chunk-7SKSRSS7.mjs → chunk-B4EAAKYF.mjs} +16 -16
- package/dist/{chunk-ZJD5WMR3.mjs → chunk-C6MQBJFC.mjs} +45 -13
- package/dist/{chunk-7H3WJJYS.mjs → chunk-ESVULCFY.mjs} +12 -6
- package/dist/{chunk-GWBGK3KL.mjs → chunk-FWJIAW2E.mjs} +82 -47
- package/dist/{chunk-R727OFBR.mjs → chunk-GPYIIWD5.mjs} +404 -350
- package/dist/{chunk-OQREHJXK.mjs → chunk-IYFWAJBB.mjs} +208 -203
- package/dist/{chunk-2JQSKIWR.mjs → chunk-MGLAKMDP.mjs} +24 -23
- package/dist/{chunk-LT3ZJJL6.mjs → chunk-OJWVEEMM.mjs} +497 -399
- package/dist/{chunk-ZD2BADZO.mjs → chunk-ORVDYXDP.mjs} +221 -175
- package/dist/{chunk-CV4M7CNU.mjs → chunk-QQVHGJ2G.mjs} +149 -142
- package/dist/{chunk-6PSJTBNV.mjs → chunk-U4QPE4CY.mjs} +387 -347
- package/dist/{chunk-EFXQT23N.mjs → chunk-VVQ4CH77.mjs} +5 -5
- package/dist/{chunk-VRN3UWE5.mjs → chunk-XRC3O5GK.mjs} +73 -73
- package/dist/{chunk-FT33LFII.mjs → chunk-YUIK4AHM.mjs} +1 -1
- package/dist/{chunk-JT4Y5H3U.mjs → chunk-ZSITTZ4S.mjs} +630 -569
- package/dist/hooks.d.ts +37 -37
- package/dist/hooks.mjs +10 -10
- package/dist/index.d.ts +26 -11
- package/dist/index.mjs +99 -20
- package/dist/lib.d.ts +203 -203
- package/dist/lib.mjs +228 -199
- package/dist/nodes.d.ts +2 -2
- package/dist/nodes.mjs +12 -13
- package/dist/panels.d.ts +2 -3
- package/dist/panels.mjs +3 -3
- package/dist/provider.d.ts +2 -2
- package/dist/provider.mjs +2 -2
- package/dist/stores.d.ts +5 -5
- package/dist/stores.mjs +5 -5
- package/dist/toolbar.d.ts +42 -24
- package/dist/toolbar.mjs +4 -5
- package/dist/ui.d.ts +2 -2
- package/dist/ui.mjs +2 -2
- package/dist/{useCommentNavigation-BakbiiIc.d.ts → useRequiredInputs-ByoIS-fT.d.ts} +160 -160
- package/dist/{promptLibraryStore-Dl3Q3cP6.d.ts → workflowStore-Bsz0nd5c.d.ts} +368 -368
- package/dist/workflowStore-N2F7WIG3.mjs +2 -0
- package/package.json +79 -77
- package/src/styles/workflow-ui.css +56 -19
- package/dist/chunk-OY7BRSGG.mjs +0 -60
- package/dist/workflowStore-UAAKOOIK.mjs +0 -2
- package/dist/{types-IEKYuYhu.d.ts → types-CRXJnajq.d.ts} +1 -1
|
@@ -1,78 +1,228 @@
|
|
|
1
|
-
import { useExecutionStore, useUIStore } from './chunk-
|
|
2
|
-
import {
|
|
3
|
-
import { Bug, Trash2, X, ChevronDown, ChevronRight, Copy, PanelLeftClose, Search, GitBranch, ArrowLeftFromLine, ArrowRightToLine, Download, Eye, CheckCircle, Columns2, LayoutGrid, Subtitles, Pencil, Grid3X3, Maximize, Crop, Film, Scissors, Layers, Wand2, Maximize2, Navigation, AudioLines, Mic, Brain, Video, Sparkles, Puzzle, Volume2, FileVideo, FileText, MessageSquare, Image } from 'lucide-react';
|
|
1
|
+
import { useExecutionStore, useUIStore } from './chunk-OJWVEEMM.mjs';
|
|
2
|
+
import { Bug, Trash2, X, ChevronDown, ChevronRight, Copy, PanelLeftClose, Search, Wand2, Volume2, Video, Subtitles, Sparkles, Scissors, Puzzle, Pencil, Navigation, Mic, MessageSquare, Maximize2, Maximize, LayoutGrid, Layers, Image, Grid3X3, GitBranch, Film, FileVideo, FileText, Eye, Download, Crop, Columns2, CheckCircle, Brain, AudioLines, ArrowRightToLine, ArrowLeftFromLine } from 'lucide-react';
|
|
4
3
|
import { forwardRef, memo, useCallback, useState, useMemo } from 'react';
|
|
5
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
import { getNodesByCategory } from '@genfeedai/types';
|
|
6
6
|
|
|
7
|
+
var PanelContainer = forwardRef(
|
|
8
|
+
({ children, className, ...props }, ref) => {
|
|
9
|
+
const stopPropagation = (e) => {
|
|
10
|
+
e.stopPropagation();
|
|
11
|
+
};
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
"div",
|
|
14
|
+
{
|
|
15
|
+
ref,
|
|
16
|
+
className,
|
|
17
|
+
onClick: stopPropagation,
|
|
18
|
+
onMouseDown: stopPropagation,
|
|
19
|
+
onPointerDown: stopPropagation,
|
|
20
|
+
onDoubleClick: stopPropagation,
|
|
21
|
+
...props,
|
|
22
|
+
children
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
PanelContainer.displayName = "PanelContainer";
|
|
28
|
+
function PayloadCard({ payload }) {
|
|
29
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
30
|
+
const [copied, setCopied] = useState(false);
|
|
31
|
+
const handleCopy = useCallback(
|
|
32
|
+
async (e) => {
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
try {
|
|
35
|
+
await navigator.clipboard.writeText(
|
|
36
|
+
JSON.stringify(payload.input, null, 2)
|
|
37
|
+
);
|
|
38
|
+
setCopied(true);
|
|
39
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
40
|
+
} catch {
|
|
41
|
+
const textArea = document.createElement("textarea");
|
|
42
|
+
textArea.value = JSON.stringify(payload.input, null, 2);
|
|
43
|
+
textArea.style.position = "fixed";
|
|
44
|
+
textArea.style.left = "-9999px";
|
|
45
|
+
document.body.appendChild(textArea);
|
|
46
|
+
textArea.select();
|
|
47
|
+
try {
|
|
48
|
+
document.execCommand("copy");
|
|
49
|
+
setCopied(true);
|
|
50
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
51
|
+
} catch {
|
|
52
|
+
}
|
|
53
|
+
document.body.removeChild(textArea);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
[payload.input]
|
|
57
|
+
);
|
|
58
|
+
const timestamp = new Date(payload.timestamp).toLocaleTimeString();
|
|
59
|
+
return /* @__PURE__ */ jsxs("div", { className: "border border-[var(--border)] rounded-lg overflow-hidden", children: [
|
|
60
|
+
/* @__PURE__ */ jsxs(
|
|
61
|
+
"button",
|
|
62
|
+
{
|
|
63
|
+
onClick: () => setIsExpanded(!isExpanded),
|
|
64
|
+
className: "w-full flex items-center gap-2 p-3 text-left hover:bg-[var(--muted)]/50 transition",
|
|
65
|
+
children: [
|
|
66
|
+
isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-4 h-4 text-[var(--muted-foreground)] shrink-0" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4 text-[var(--muted-foreground)] shrink-0" }),
|
|
67
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
68
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
69
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-[var(--foreground)] truncate", children: payload.nodeName || payload.nodeId }),
|
|
70
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] px-1.5 py-0.5 bg-amber-500/10 text-amber-500 rounded", children: payload.nodeType })
|
|
71
|
+
] }),
|
|
72
|
+
/* @__PURE__ */ jsxs("div", { className: "text-[10px] text-[var(--muted-foreground)] mt-0.5", children: [
|
|
73
|
+
payload.model,
|
|
74
|
+
" \u2022 ",
|
|
75
|
+
timestamp
|
|
76
|
+
] })
|
|
77
|
+
] })
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
isExpanded && /* @__PURE__ */ jsxs("div", { className: "border-t border-[var(--border)] p-3 bg-[var(--muted)]/30", children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
83
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-[var(--muted-foreground)] uppercase", children: "Payload" }),
|
|
84
|
+
/* @__PURE__ */ jsxs(
|
|
85
|
+
"button",
|
|
86
|
+
{
|
|
87
|
+
onClick: handleCopy,
|
|
88
|
+
className: "flex items-center gap-1 text-[10px] text-[var(--primary)] hover:underline",
|
|
89
|
+
children: [
|
|
90
|
+
/* @__PURE__ */ jsx(Copy, { className: "w-3 h-3" }),
|
|
91
|
+
copied ? "Copied!" : "Copy"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
] }),
|
|
96
|
+
/* @__PURE__ */ jsx("pre", { className: "text-[11px] font-mono text-[var(--muted-foreground)] bg-[var(--background)] p-2 rounded border border-[var(--border)] overflow-x-auto max-h-64 overflow-y-auto", children: JSON.stringify(payload.input, null, 2) })
|
|
97
|
+
] })
|
|
98
|
+
] });
|
|
99
|
+
}
|
|
100
|
+
function DebugPanelComponent() {
|
|
101
|
+
const debugPayloads = useExecutionStore((s) => s.debugPayloads);
|
|
102
|
+
const clearDebugPayloads = useExecutionStore((s) => s.clearDebugPayloads);
|
|
103
|
+
const setShowDebugPanel = useUIStore((s) => s.setShowDebugPanel);
|
|
104
|
+
const handleClose = useCallback(() => {
|
|
105
|
+
setShowDebugPanel(false);
|
|
106
|
+
}, [setShowDebugPanel]);
|
|
107
|
+
return /* @__PURE__ */ jsxs(PanelContainer, { className: "w-80 h-full border-l border-[var(--border)] bg-[var(--background)] flex flex-col", children: [
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 border-b border-[var(--border)]", children: [
|
|
109
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
110
|
+
/* @__PURE__ */ jsx(Bug, { className: "w-4 h-4 text-amber-500" }),
|
|
111
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: "Debug Console" }),
|
|
112
|
+
debugPayloads.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] px-1.5 py-0.5 bg-amber-500/10 text-amber-500 rounded-full", children: debugPayloads.length })
|
|
113
|
+
] }),
|
|
114
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
115
|
+
debugPayloads.length > 0 && /* @__PURE__ */ jsx(
|
|
116
|
+
"button",
|
|
117
|
+
{
|
|
118
|
+
onClick: clearDebugPayloads,
|
|
119
|
+
className: "p-1.5 hover:bg-[var(--muted)] rounded transition",
|
|
120
|
+
title: "Clear all payloads",
|
|
121
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4 text-[var(--muted-foreground)]" })
|
|
122
|
+
}
|
|
123
|
+
),
|
|
124
|
+
/* @__PURE__ */ jsx(
|
|
125
|
+
"button",
|
|
126
|
+
{
|
|
127
|
+
onClick: handleClose,
|
|
128
|
+
className: "p-1.5 hover:bg-[var(--muted)] rounded transition",
|
|
129
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
] })
|
|
133
|
+
] }),
|
|
134
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-3 space-y-2", children: debugPayloads.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-[var(--muted-foreground)]", children: [
|
|
135
|
+
/* @__PURE__ */ jsx(Bug, { className: "w-12 h-12 mx-auto mb-3 opacity-50 text-amber-500/50" }),
|
|
136
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium mb-2", children: "No payloads captured" }),
|
|
137
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs", children: "Run a workflow with debug mode enabled to capture API payloads." })
|
|
138
|
+
] }) : debugPayloads.map((payload, index) => /* @__PURE__ */ jsx(
|
|
139
|
+
PayloadCard,
|
|
140
|
+
{
|
|
141
|
+
payload
|
|
142
|
+
},
|
|
143
|
+
`${payload.nodeId}-${payload.timestamp}-${index}`
|
|
144
|
+
)) }),
|
|
145
|
+
debugPayloads.length > 0 && /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-[var(--border)] bg-[var(--muted)]/30", children: /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-[var(--muted-foreground)]", children: [
|
|
146
|
+
debugPayloads.length,
|
|
147
|
+
" payload",
|
|
148
|
+
debugPayloads.length !== 1 ? "s" : "",
|
|
149
|
+
" captured. Click to expand and view details."
|
|
150
|
+
] }) })
|
|
151
|
+
] });
|
|
152
|
+
}
|
|
153
|
+
var MemoizedDebugPanel = memo(DebugPanelComponent);
|
|
154
|
+
function DebugPanel() {
|
|
155
|
+
return /* @__PURE__ */ jsx(MemoizedDebugPanel, {});
|
|
156
|
+
}
|
|
7
157
|
var ICONS = {
|
|
158
|
+
ArrowLeftFromLine,
|
|
159
|
+
// Composition
|
|
160
|
+
ArrowRightToLine,
|
|
161
|
+
AudioLines,
|
|
162
|
+
Brain,
|
|
163
|
+
// Output
|
|
164
|
+
CheckCircle,
|
|
165
|
+
Columns2,
|
|
166
|
+
Crop,
|
|
167
|
+
Download,
|
|
168
|
+
Eye,
|
|
169
|
+
FileText,
|
|
170
|
+
FileVideo,
|
|
171
|
+
Film,
|
|
172
|
+
GitBranch,
|
|
173
|
+
Grid3X3,
|
|
8
174
|
// Input
|
|
9
175
|
Image,
|
|
176
|
+
Layers,
|
|
177
|
+
LayoutGrid,
|
|
178
|
+
Maximize,
|
|
179
|
+
// Processing
|
|
180
|
+
Maximize2,
|
|
10
181
|
MessageSquare,
|
|
11
|
-
FileText,
|
|
12
|
-
FileVideo,
|
|
13
|
-
Volume2,
|
|
14
|
-
Puzzle,
|
|
15
|
-
// AI
|
|
16
|
-
Sparkles,
|
|
17
|
-
Video,
|
|
18
|
-
Brain,
|
|
19
182
|
Mic,
|
|
20
|
-
AudioLines,
|
|
21
183
|
Navigation,
|
|
22
|
-
// Processing
|
|
23
|
-
Maximize2,
|
|
24
|
-
Wand2,
|
|
25
|
-
Layers,
|
|
26
|
-
Scissors,
|
|
27
|
-
Film,
|
|
28
|
-
Crop,
|
|
29
|
-
Maximize,
|
|
30
|
-
Grid3X3,
|
|
31
184
|
Pencil,
|
|
185
|
+
Puzzle,
|
|
186
|
+
Scissors,
|
|
187
|
+
// AI
|
|
188
|
+
Sparkles,
|
|
32
189
|
Subtitles,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
CheckCircle,
|
|
37
|
-
Eye,
|
|
38
|
-
Download,
|
|
39
|
-
// Composition
|
|
40
|
-
ArrowRightToLine,
|
|
41
|
-
ArrowLeftFromLine,
|
|
42
|
-
GitBranch
|
|
190
|
+
Video,
|
|
191
|
+
Volume2,
|
|
192
|
+
Wand2
|
|
43
193
|
};
|
|
44
194
|
var CATEGORY_LABELS = {
|
|
45
|
-
input: "Input",
|
|
46
195
|
ai: "AI Generation",
|
|
47
|
-
|
|
196
|
+
composition: "Composition",
|
|
197
|
+
input: "Input",
|
|
48
198
|
output: "Output",
|
|
49
|
-
|
|
199
|
+
processing: "Processing"
|
|
50
200
|
};
|
|
51
201
|
var CATEGORY_COLORS = {
|
|
52
|
-
input: {
|
|
53
|
-
icon: "bg-[var(--category-input)]/20 text-[var(--category-input)]",
|
|
54
|
-
hover: "hover:border-[var(--category-input)]",
|
|
55
|
-
cssVar: "var(--category-input)"
|
|
56
|
-
},
|
|
57
202
|
ai: {
|
|
58
|
-
|
|
203
|
+
cssVar: "var(--category-ai)",
|
|
59
204
|
hover: "hover:border-[var(--category-ai)]",
|
|
60
|
-
|
|
205
|
+
icon: "bg-[var(--category-ai)]/20 text-[var(--category-ai)]"
|
|
61
206
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
hover: "hover:border-[var(--category-
|
|
65
|
-
|
|
207
|
+
composition: {
|
|
208
|
+
cssVar: "var(--category-composition)",
|
|
209
|
+
hover: "hover:border-[var(--category-composition)]",
|
|
210
|
+
icon: "bg-[var(--category-composition)]/20 text-[var(--category-composition)]"
|
|
211
|
+
},
|
|
212
|
+
input: {
|
|
213
|
+
cssVar: "var(--category-input)",
|
|
214
|
+
hover: "hover:border-[var(--category-input)]",
|
|
215
|
+
icon: "bg-[var(--category-input)]/20 text-[var(--category-input)]"
|
|
66
216
|
},
|
|
67
217
|
output: {
|
|
68
|
-
|
|
218
|
+
cssVar: "var(--category-output)",
|
|
69
219
|
hover: "hover:border-[var(--category-output)]",
|
|
70
|
-
|
|
220
|
+
icon: "bg-[var(--category-output)]/20 text-[var(--category-output)]"
|
|
71
221
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
hover: "hover:border-[var(--category-
|
|
75
|
-
|
|
222
|
+
processing: {
|
|
223
|
+
cssVar: "var(--category-processing)",
|
|
224
|
+
hover: "hover:border-[var(--category-processing)]",
|
|
225
|
+
icon: "bg-[var(--category-processing)]/20 text-[var(--category-processing)]"
|
|
76
226
|
}
|
|
77
227
|
};
|
|
78
228
|
function NodeCard({ type, label, description, icon, category }) {
|
|
@@ -101,7 +251,11 @@ function NodeCard({ type, label, description, icon, category }) {
|
|
|
101
251
|
}
|
|
102
252
|
);
|
|
103
253
|
}
|
|
104
|
-
function CategorySection({
|
|
254
|
+
function CategorySection({
|
|
255
|
+
category,
|
|
256
|
+
isExpanded,
|
|
257
|
+
onToggle
|
|
258
|
+
}) {
|
|
105
259
|
const nodes = getNodesByCategory()[category];
|
|
106
260
|
return /* @__PURE__ */ jsxs("div", { className: "border-b border-[var(--border)] last:border-0", children: [
|
|
107
261
|
/* @__PURE__ */ jsxs(
|
|
@@ -132,9 +286,7 @@ function CategorySection({ category, isExpanded, onToggle }) {
|
|
|
132
286
|
function NodePalette() {
|
|
133
287
|
const { togglePalette } = useUIStore();
|
|
134
288
|
const [searchQuery, setSearchQuery] = useState("");
|
|
135
|
-
const [expandedCategories, setExpandedCategories] = useState(
|
|
136
|
-
/* @__PURE__ */ new Set(["input"])
|
|
137
|
-
);
|
|
289
|
+
const [expandedCategories, setExpandedCategories] = useState(/* @__PURE__ */ new Set(["input"]));
|
|
138
290
|
const nodesByCategory = useMemo(() => getNodesByCategory(), []);
|
|
139
291
|
const filteredNodes = useMemo(() => {
|
|
140
292
|
if (!searchQuery.trim()) return null;
|
|
@@ -161,9 +313,7 @@ function NodePalette() {
|
|
|
161
313
|
});
|
|
162
314
|
}, []);
|
|
163
315
|
const categories = useMemo(
|
|
164
|
-
() => ["input", "ai", "processing", "output", "composition"].filter(
|
|
165
|
-
(cat) => nodesByCategory[cat].length > 0
|
|
166
|
-
),
|
|
316
|
+
() => ["input", "ai", "processing", "output", "composition"].filter((cat) => nodesByCategory[cat].length > 0),
|
|
167
317
|
[nodesByCategory]
|
|
168
318
|
);
|
|
169
319
|
return /* @__PURE__ */ jsxs("div", { className: "w-64 min-w-64 h-full bg-[var(--background)] border-r border-[var(--border)] flex flex-col overflow-hidden", children: [
|
|
@@ -222,150 +372,5 @@ function NodePalette() {
|
|
|
222
372
|
) })
|
|
223
373
|
] });
|
|
224
374
|
}
|
|
225
|
-
var PanelContainer = forwardRef(
|
|
226
|
-
({ children, className, ...props }, ref) => {
|
|
227
|
-
const stopPropagation = (e) => {
|
|
228
|
-
e.stopPropagation();
|
|
229
|
-
};
|
|
230
|
-
return /* @__PURE__ */ jsx(
|
|
231
|
-
"div",
|
|
232
|
-
{
|
|
233
|
-
ref,
|
|
234
|
-
className,
|
|
235
|
-
onClick: stopPropagation,
|
|
236
|
-
onMouseDown: stopPropagation,
|
|
237
|
-
onPointerDown: stopPropagation,
|
|
238
|
-
onDoubleClick: stopPropagation,
|
|
239
|
-
...props,
|
|
240
|
-
children
|
|
241
|
-
}
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
);
|
|
245
|
-
PanelContainer.displayName = "PanelContainer";
|
|
246
|
-
function PayloadCard({ payload }) {
|
|
247
|
-
const [isExpanded, setIsExpanded] = useState(false);
|
|
248
|
-
const [copied, setCopied] = useState(false);
|
|
249
|
-
const handleCopy = useCallback(
|
|
250
|
-
async (e) => {
|
|
251
|
-
e.stopPropagation();
|
|
252
|
-
try {
|
|
253
|
-
await navigator.clipboard.writeText(JSON.stringify(payload.input, null, 2));
|
|
254
|
-
setCopied(true);
|
|
255
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
256
|
-
} catch {
|
|
257
|
-
const textArea = document.createElement("textarea");
|
|
258
|
-
textArea.value = JSON.stringify(payload.input, null, 2);
|
|
259
|
-
textArea.style.position = "fixed";
|
|
260
|
-
textArea.style.left = "-9999px";
|
|
261
|
-
document.body.appendChild(textArea);
|
|
262
|
-
textArea.select();
|
|
263
|
-
try {
|
|
264
|
-
document.execCommand("copy");
|
|
265
|
-
setCopied(true);
|
|
266
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
267
|
-
} catch {
|
|
268
|
-
}
|
|
269
|
-
document.body.removeChild(textArea);
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
[payload.input]
|
|
273
|
-
);
|
|
274
|
-
const timestamp = new Date(payload.timestamp).toLocaleTimeString();
|
|
275
|
-
return /* @__PURE__ */ jsxs("div", { className: "border border-[var(--border)] rounded-lg overflow-hidden", children: [
|
|
276
|
-
/* @__PURE__ */ jsxs(
|
|
277
|
-
"button",
|
|
278
|
-
{
|
|
279
|
-
onClick: () => setIsExpanded(!isExpanded),
|
|
280
|
-
className: "w-full flex items-center gap-2 p-3 text-left hover:bg-[var(--muted)]/50 transition",
|
|
281
|
-
children: [
|
|
282
|
-
isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-4 h-4 text-[var(--muted-foreground)] shrink-0" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4 text-[var(--muted-foreground)] shrink-0" }),
|
|
283
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
284
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
285
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-[var(--foreground)] truncate", children: payload.nodeName || payload.nodeId }),
|
|
286
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] px-1.5 py-0.5 bg-amber-500/10 text-amber-500 rounded", children: payload.nodeType })
|
|
287
|
-
] }),
|
|
288
|
-
/* @__PURE__ */ jsxs("div", { className: "text-[10px] text-[var(--muted-foreground)] mt-0.5", children: [
|
|
289
|
-
payload.model,
|
|
290
|
-
" \u2022 ",
|
|
291
|
-
timestamp
|
|
292
|
-
] })
|
|
293
|
-
] })
|
|
294
|
-
]
|
|
295
|
-
}
|
|
296
|
-
),
|
|
297
|
-
isExpanded && /* @__PURE__ */ jsxs("div", { className: "border-t border-[var(--border)] p-3 bg-[var(--muted)]/30", children: [
|
|
298
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
299
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-[var(--muted-foreground)] uppercase", children: "Payload" }),
|
|
300
|
-
/* @__PURE__ */ jsxs(
|
|
301
|
-
"button",
|
|
302
|
-
{
|
|
303
|
-
onClick: handleCopy,
|
|
304
|
-
className: "flex items-center gap-1 text-[10px] text-[var(--primary)] hover:underline",
|
|
305
|
-
children: [
|
|
306
|
-
/* @__PURE__ */ jsx(Copy, { className: "w-3 h-3" }),
|
|
307
|
-
copied ? "Copied!" : "Copy"
|
|
308
|
-
]
|
|
309
|
-
}
|
|
310
|
-
)
|
|
311
|
-
] }),
|
|
312
|
-
/* @__PURE__ */ jsx("pre", { className: "text-[11px] font-mono text-[var(--muted-foreground)] bg-[var(--background)] p-2 rounded border border-[var(--border)] overflow-x-auto max-h-64 overflow-y-auto", children: JSON.stringify(payload.input, null, 2) })
|
|
313
|
-
] })
|
|
314
|
-
] });
|
|
315
|
-
}
|
|
316
|
-
function DebugPanelComponent() {
|
|
317
|
-
const debugPayloads = useExecutionStore((s) => s.debugPayloads);
|
|
318
|
-
const clearDebugPayloads = useExecutionStore((s) => s.clearDebugPayloads);
|
|
319
|
-
const setShowDebugPanel = useUIStore((s) => s.setShowDebugPanel);
|
|
320
|
-
const handleClose = useCallback(() => {
|
|
321
|
-
setShowDebugPanel(false);
|
|
322
|
-
}, [setShowDebugPanel]);
|
|
323
|
-
return /* @__PURE__ */ jsxs(PanelContainer, { className: "w-80 h-full border-l border-[var(--border)] bg-[var(--background)] flex flex-col", children: [
|
|
324
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 border-b border-[var(--border)]", children: [
|
|
325
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
326
|
-
/* @__PURE__ */ jsx(Bug, { className: "w-4 h-4 text-amber-500" }),
|
|
327
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: "Debug Console" }),
|
|
328
|
-
debugPayloads.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] px-1.5 py-0.5 bg-amber-500/10 text-amber-500 rounded-full", children: debugPayloads.length })
|
|
329
|
-
] }),
|
|
330
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
331
|
-
debugPayloads.length > 0 && /* @__PURE__ */ jsx(
|
|
332
|
-
"button",
|
|
333
|
-
{
|
|
334
|
-
onClick: clearDebugPayloads,
|
|
335
|
-
className: "p-1.5 hover:bg-[var(--muted)] rounded transition",
|
|
336
|
-
title: "Clear all payloads",
|
|
337
|
-
children: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4 text-[var(--muted-foreground)]" })
|
|
338
|
-
}
|
|
339
|
-
),
|
|
340
|
-
/* @__PURE__ */ jsx(
|
|
341
|
-
"button",
|
|
342
|
-
{
|
|
343
|
-
onClick: handleClose,
|
|
344
|
-
className: "p-1.5 hover:bg-[var(--muted)] rounded transition",
|
|
345
|
-
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
346
|
-
}
|
|
347
|
-
)
|
|
348
|
-
] })
|
|
349
|
-
] }),
|
|
350
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-3 space-y-2", children: debugPayloads.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-[var(--muted-foreground)]", children: [
|
|
351
|
-
/* @__PURE__ */ jsx(Bug, { className: "w-12 h-12 mx-auto mb-3 opacity-50 text-amber-500/50" }),
|
|
352
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium mb-2", children: "No payloads captured" }),
|
|
353
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs", children: "Run a workflow with debug mode enabled to capture API payloads." })
|
|
354
|
-
] }) : debugPayloads.map((payload, index) => /* @__PURE__ */ jsx(
|
|
355
|
-
PayloadCard,
|
|
356
|
-
{
|
|
357
|
-
payload
|
|
358
|
-
},
|
|
359
|
-
`${payload.nodeId}-${payload.timestamp}-${index}`
|
|
360
|
-
)) }),
|
|
361
|
-
debugPayloads.length > 0 && /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-[var(--border)] bg-[var(--muted)]/30", children: /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-[var(--muted-foreground)]", children: [
|
|
362
|
-
debugPayloads.length,
|
|
363
|
-
" payload",
|
|
364
|
-
debugPayloads.length !== 1 ? "s" : "",
|
|
365
|
-
" captured. Click to expand and view details."
|
|
366
|
-
] }) })
|
|
367
|
-
] });
|
|
368
|
-
}
|
|
369
|
-
var DebugPanel = memo(DebugPanelComponent);
|
|
370
375
|
|
|
371
376
|
export { DebugPanel, NodePalette, PanelContainer };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { PRICING, DEFAULT_VIDEO_DURATION, IMAGE_NODE_TYPES, VIDEO_NODE_TYPES, LUMA_NODE_TYPES, TOPAZ_NODE_TYPES } from '
|
|
1
|
+
import { PRICING, DEFAULT_VIDEO_DURATION, IMAGE_NODE_TYPES, VIDEO_NODE_TYPES, LUMA_NODE_TYPES, TOPAZ_NODE_TYPES } from '@genfeedai/core';
|
|
2
2
|
|
|
3
|
-
// src/lib/costCalculator.ts
|
|
4
3
|
function isNodeType(type, list) {
|
|
5
4
|
return list.includes(type);
|
|
6
5
|
}
|
|
@@ -24,14 +23,14 @@ function calculateWorkflowCost(nodes) {
|
|
|
24
23
|
cost = priceEntry[resolution] ?? Object.values(priceEntry)[0] ?? 0;
|
|
25
24
|
}
|
|
26
25
|
estimates.push({
|
|
26
|
+
model,
|
|
27
27
|
nodeId: node.id,
|
|
28
28
|
nodeLabel: label,
|
|
29
29
|
nodeType: type,
|
|
30
|
-
model,
|
|
31
|
-
unitPrice: cost,
|
|
32
30
|
quantity: 1,
|
|
33
31
|
subtotal: cost,
|
|
34
|
-
unit: "per image"
|
|
32
|
+
unit: "per image",
|
|
33
|
+
unitPrice: cost
|
|
35
34
|
});
|
|
36
35
|
continue;
|
|
37
36
|
}
|
|
@@ -47,15 +46,15 @@ function calculateWorkflowCost(nodes) {
|
|
|
47
46
|
}
|
|
48
47
|
const subtotal = perSecond * duration;
|
|
49
48
|
estimates.push({
|
|
49
|
+
duration,
|
|
50
|
+
model,
|
|
50
51
|
nodeId: node.id,
|
|
51
52
|
nodeLabel: label,
|
|
52
53
|
nodeType: type,
|
|
53
|
-
model,
|
|
54
|
-
unitPrice: perSecond,
|
|
55
54
|
quantity: duration,
|
|
56
55
|
subtotal,
|
|
57
56
|
unit: `${duration}s video`,
|
|
58
|
-
|
|
57
|
+
unitPrice: perSecond,
|
|
59
58
|
withAudio: generateAudio
|
|
60
59
|
});
|
|
61
60
|
continue;
|
|
@@ -71,14 +70,14 @@ function calculateWorkflowCost(nodes) {
|
|
|
71
70
|
subtotal = imageEntry[model] ?? 0.01;
|
|
72
71
|
}
|
|
73
72
|
estimates.push({
|
|
73
|
+
model,
|
|
74
74
|
nodeId: node.id,
|
|
75
75
|
nodeLabel: label,
|
|
76
76
|
nodeType: type,
|
|
77
|
-
model,
|
|
78
|
-
unitPrice: subtotal,
|
|
79
77
|
quantity: 1,
|
|
80
78
|
subtotal,
|
|
81
|
-
unit: inputType === "video" ? "per video" : "per image"
|
|
79
|
+
unit: inputType === "video" ? "per video" : "per image",
|
|
80
|
+
unitPrice: subtotal
|
|
82
81
|
});
|
|
83
82
|
continue;
|
|
84
83
|
}
|
|
@@ -92,27 +91,29 @@ function calculateWorkflowCost(nodes) {
|
|
|
92
91
|
const duration = DEFAULT_VIDEO_DURATION;
|
|
93
92
|
const chunks = Math.ceil(duration / 5);
|
|
94
93
|
estimates.push({
|
|
94
|
+
duration,
|
|
95
|
+
model: "topaz-video",
|
|
95
96
|
nodeId: node.id,
|
|
96
97
|
nodeLabel: label,
|
|
97
98
|
nodeType: type,
|
|
98
|
-
model: "topaz-video",
|
|
99
|
-
unitPrice: pricePerChunk,
|
|
100
99
|
quantity: chunks,
|
|
101
100
|
subtotal: pricePerChunk * chunks,
|
|
102
101
|
unit: `${duration}s video`,
|
|
103
|
-
|
|
102
|
+
unitPrice: pricePerChunk
|
|
104
103
|
});
|
|
105
104
|
} else {
|
|
106
|
-
const tier = PRICING["topaz-image-upscale"].find(
|
|
105
|
+
const tier = PRICING["topaz-image-upscale"].find(
|
|
106
|
+
(t) => 1 <= t.maxMP
|
|
107
|
+
) ?? PRICING["topaz-image-upscale"][0];
|
|
107
108
|
estimates.push({
|
|
109
|
+
model: getDataField(data, "model", "topaz-standard-v2"),
|
|
108
110
|
nodeId: node.id,
|
|
109
111
|
nodeLabel: label,
|
|
110
112
|
nodeType: type,
|
|
111
|
-
model: getDataField(data, "model", "topaz-standard-v2"),
|
|
112
|
-
unitPrice: tier.price,
|
|
113
113
|
quantity: 1,
|
|
114
114
|
subtotal: tier.price,
|
|
115
|
-
unit: "per image"
|
|
115
|
+
unit: "per image",
|
|
116
|
+
unitPrice: tier.price
|
|
116
117
|
});
|
|
117
118
|
}
|
|
118
119
|
continue;
|
|
@@ -122,20 +123,20 @@ function calculateWorkflowCost(nodes) {
|
|
|
122
123
|
const estimatedTokens = maxTokens * 3;
|
|
123
124
|
const subtotal = estimatedTokens * PRICING.llama;
|
|
124
125
|
estimates.push({
|
|
126
|
+
model: getDataField(data, "model", "llama"),
|
|
125
127
|
nodeId: node.id,
|
|
126
128
|
nodeLabel: label,
|
|
127
129
|
nodeType: type,
|
|
128
|
-
model: getDataField(data, "model", "llama"),
|
|
129
|
-
unitPrice: PRICING.llama,
|
|
130
130
|
quantity: estimatedTokens,
|
|
131
131
|
subtotal,
|
|
132
|
-
unit: `~${estimatedTokens} tokens
|
|
132
|
+
unit: `~${estimatedTokens} tokens`,
|
|
133
|
+
unitPrice: PRICING.llama
|
|
133
134
|
});
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
return {
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
items: estimates,
|
|
139
|
+
total: estimates.reduce((sum, e) => sum + e.subtotal, 0)
|
|
139
140
|
};
|
|
140
141
|
}
|
|
141
142
|
function formatCost(amount) {
|