@genfeedai/workflow-ui 0.2.3 → 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/dist/canvas.d.ts +22 -22
- package/dist/canvas.mjs +16 -16
- package/dist/{chunk-XPZAHIWY.mjs → chunk-2FUPL67V.mjs} +1592 -1044
- package/dist/{chunk-HWVTD2LC.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-N5NJZTK4.mjs → chunk-MGLAKMDP.mjs} +23 -21
- 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-FMJPFB6W.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 -19
- package/dist/lib.d.ts +203 -203
- package/dist/lib.mjs +228 -198
- package/dist/nodes.d.ts +2 -2
- package/dist/nodes.mjs +12 -12
- 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 -4
- 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 +77 -75
- package/src/styles/workflow-ui.css +56 -19
- 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 };
|
|
@@ -23,14 +23,14 @@ function calculateWorkflowCost(nodes) {
|
|
|
23
23
|
cost = priceEntry[resolution] ?? Object.values(priceEntry)[0] ?? 0;
|
|
24
24
|
}
|
|
25
25
|
estimates.push({
|
|
26
|
+
model,
|
|
26
27
|
nodeId: node.id,
|
|
27
28
|
nodeLabel: label,
|
|
28
29
|
nodeType: type,
|
|
29
|
-
model,
|
|
30
|
-
unitPrice: cost,
|
|
31
30
|
quantity: 1,
|
|
32
31
|
subtotal: cost,
|
|
33
|
-
unit: "per image"
|
|
32
|
+
unit: "per image",
|
|
33
|
+
unitPrice: cost
|
|
34
34
|
});
|
|
35
35
|
continue;
|
|
36
36
|
}
|
|
@@ -46,15 +46,15 @@ function calculateWorkflowCost(nodes) {
|
|
|
46
46
|
}
|
|
47
47
|
const subtotal = perSecond * duration;
|
|
48
48
|
estimates.push({
|
|
49
|
+
duration,
|
|
50
|
+
model,
|
|
49
51
|
nodeId: node.id,
|
|
50
52
|
nodeLabel: label,
|
|
51
53
|
nodeType: type,
|
|
52
|
-
model,
|
|
53
|
-
unitPrice: perSecond,
|
|
54
54
|
quantity: duration,
|
|
55
55
|
subtotal,
|
|
56
56
|
unit: `${duration}s video`,
|
|
57
|
-
|
|
57
|
+
unitPrice: perSecond,
|
|
58
58
|
withAudio: generateAudio
|
|
59
59
|
});
|
|
60
60
|
continue;
|
|
@@ -70,14 +70,14 @@ function calculateWorkflowCost(nodes) {
|
|
|
70
70
|
subtotal = imageEntry[model] ?? 0.01;
|
|
71
71
|
}
|
|
72
72
|
estimates.push({
|
|
73
|
+
model,
|
|
73
74
|
nodeId: node.id,
|
|
74
75
|
nodeLabel: label,
|
|
75
76
|
nodeType: type,
|
|
76
|
-
model,
|
|
77
|
-
unitPrice: subtotal,
|
|
78
77
|
quantity: 1,
|
|
79
78
|
subtotal,
|
|
80
|
-
unit: inputType === "video" ? "per video" : "per image"
|
|
79
|
+
unit: inputType === "video" ? "per video" : "per image",
|
|
80
|
+
unitPrice: subtotal
|
|
81
81
|
});
|
|
82
82
|
continue;
|
|
83
83
|
}
|
|
@@ -91,27 +91,29 @@ function calculateWorkflowCost(nodes) {
|
|
|
91
91
|
const duration = DEFAULT_VIDEO_DURATION;
|
|
92
92
|
const chunks = Math.ceil(duration / 5);
|
|
93
93
|
estimates.push({
|
|
94
|
+
duration,
|
|
95
|
+
model: "topaz-video",
|
|
94
96
|
nodeId: node.id,
|
|
95
97
|
nodeLabel: label,
|
|
96
98
|
nodeType: type,
|
|
97
|
-
model: "topaz-video",
|
|
98
|
-
unitPrice: pricePerChunk,
|
|
99
99
|
quantity: chunks,
|
|
100
100
|
subtotal: pricePerChunk * chunks,
|
|
101
101
|
unit: `${duration}s video`,
|
|
102
|
-
|
|
102
|
+
unitPrice: pricePerChunk
|
|
103
103
|
});
|
|
104
104
|
} else {
|
|
105
|
-
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];
|
|
106
108
|
estimates.push({
|
|
109
|
+
model: getDataField(data, "model", "topaz-standard-v2"),
|
|
107
110
|
nodeId: node.id,
|
|
108
111
|
nodeLabel: label,
|
|
109
112
|
nodeType: type,
|
|
110
|
-
model: getDataField(data, "model", "topaz-standard-v2"),
|
|
111
|
-
unitPrice: tier.price,
|
|
112
113
|
quantity: 1,
|
|
113
114
|
subtotal: tier.price,
|
|
114
|
-
unit: "per image"
|
|
115
|
+
unit: "per image",
|
|
116
|
+
unitPrice: tier.price
|
|
115
117
|
});
|
|
116
118
|
}
|
|
117
119
|
continue;
|
|
@@ -121,20 +123,20 @@ function calculateWorkflowCost(nodes) {
|
|
|
121
123
|
const estimatedTokens = maxTokens * 3;
|
|
122
124
|
const subtotal = estimatedTokens * PRICING.llama;
|
|
123
125
|
estimates.push({
|
|
126
|
+
model: getDataField(data, "model", "llama"),
|
|
124
127
|
nodeId: node.id,
|
|
125
128
|
nodeLabel: label,
|
|
126
129
|
nodeType: type,
|
|
127
|
-
model: getDataField(data, "model", "llama"),
|
|
128
|
-
unitPrice: PRICING.llama,
|
|
129
130
|
quantity: estimatedTokens,
|
|
130
131
|
subtotal,
|
|
131
|
-
unit: `~${estimatedTokens} tokens
|
|
132
|
+
unit: `~${estimatedTokens} tokens`,
|
|
133
|
+
unitPrice: PRICING.llama
|
|
132
134
|
});
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
return {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
items: estimates,
|
|
139
|
+
total: estimates.reduce((sum, e) => sum + e.subtotal, 0)
|
|
138
140
|
};
|
|
139
141
|
}
|
|
140
142
|
function formatCost(amount) {
|