@genfeedai/workflow-ui 0.1.3 → 0.1.5
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 +31 -25
- 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
package/dist/chunk-3TMV3K34.js
DELETED
|
@@ -1,534 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunk5HJFQVUR_js = require('./chunk-5HJFQVUR.js');
|
|
4
|
-
var chunkEMUMKW5C_js = require('./chunk-EMUMKW5C.js');
|
|
5
|
-
var chunkAXFOCPPP_js = require('./chunk-AXFOCPPP.js');
|
|
6
|
-
var chunkIHF35QZD_js = require('./chunk-IHF35QZD.js');
|
|
7
|
-
var chunkRJ262NXS_js = require('./chunk-RJ262NXS.js');
|
|
8
|
-
var react = require('react');
|
|
9
|
-
var lucideReact = require('lucide-react');
|
|
10
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
-
var types = require('@genfeedai/types');
|
|
12
|
-
var shallow = require('zustand/react/shallow');
|
|
13
|
-
|
|
14
|
-
function useAIGenNode({
|
|
15
|
-
nodeId,
|
|
16
|
-
selectedModel,
|
|
17
|
-
schemaParams
|
|
18
|
-
}) {
|
|
19
|
-
const updateNodeData = chunkIHF35QZD_js.useWorkflowStore((state) => state.updateNodeData);
|
|
20
|
-
const schemaProperties = react.useMemo(() => {
|
|
21
|
-
const schema = selectedModel?.inputSchema;
|
|
22
|
-
return schema?.properties;
|
|
23
|
-
}, [selectedModel?.inputSchema]);
|
|
24
|
-
const enumValues = react.useMemo(
|
|
25
|
-
() => chunkEMUMKW5C_js.extractEnumValues(
|
|
26
|
-
selectedModel?.componentSchemas
|
|
27
|
-
),
|
|
28
|
-
[selectedModel?.componentSchemas]
|
|
29
|
-
);
|
|
30
|
-
const modelSupportsImageInput = react.useMemo(
|
|
31
|
-
() => chunkEMUMKW5C_js.supportsImageInput(selectedModel?.inputSchema),
|
|
32
|
-
[selectedModel?.inputSchema]
|
|
33
|
-
);
|
|
34
|
-
const componentSchemas = selectedModel?.componentSchemas;
|
|
35
|
-
const handleSchemaParamChange = react.useCallback(
|
|
36
|
-
(key, value) => {
|
|
37
|
-
const currentNode = chunkIHF35QZD_js.useWorkflowStore.getState().getNodeById(nodeId);
|
|
38
|
-
const currentData = currentNode?.data;
|
|
39
|
-
updateNodeData(nodeId, {
|
|
40
|
-
schemaParams: {
|
|
41
|
-
...currentData?.schemaParams ?? {},
|
|
42
|
-
[key]: value
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
[nodeId, updateNodeData]
|
|
47
|
-
);
|
|
48
|
-
return {
|
|
49
|
-
schemaProperties,
|
|
50
|
-
enumValues,
|
|
51
|
-
modelSupportsImageInput,
|
|
52
|
-
handleSchemaParamChange,
|
|
53
|
-
componentSchemas
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
function useAIGenNodeHeader({
|
|
57
|
-
modelDisplayName,
|
|
58
|
-
isProcessing,
|
|
59
|
-
canGenerate,
|
|
60
|
-
hasOutput,
|
|
61
|
-
onModelBrowse,
|
|
62
|
-
onGenerate,
|
|
63
|
-
onStop,
|
|
64
|
-
onExpand
|
|
65
|
-
}) {
|
|
66
|
-
const titleElement = react.useMemo(
|
|
67
|
-
() => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
68
|
-
"button",
|
|
69
|
-
{
|
|
70
|
-
className: `flex flex-1 items-center gap-1 text-sm font-medium text-left text-foreground ${isProcessing ? "opacity-50 cursor-default" : "hover:text-foreground/80 cursor-pointer"}`,
|
|
71
|
-
onClick: () => !isProcessing && onModelBrowse(),
|
|
72
|
-
title: "Browse models",
|
|
73
|
-
disabled: isProcessing,
|
|
74
|
-
children: [
|
|
75
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: modelDisplayName }),
|
|
76
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3 w-3 shrink-0" })
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
),
|
|
80
|
-
[modelDisplayName, isProcessing, onModelBrowse]
|
|
81
|
-
);
|
|
82
|
-
const headerActions = react.useMemo(
|
|
83
|
-
() => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
84
|
-
hasOutput && /* @__PURE__ */ jsxRuntime.jsx(chunk5HJFQVUR_js.Button, { variant: "ghost", size: "icon-sm", onClick: onExpand, title: "Expand preview", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Expand, { className: "h-3 w-3" }) }),
|
|
85
|
-
isProcessing ? /* @__PURE__ */ jsxRuntime.jsxs(chunk5HJFQVUR_js.Button, { variant: "destructive", size: "sm", onClick: onStop, children: [
|
|
86
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { className: "h-4 w-4 fill-current" }),
|
|
87
|
-
"Generating"
|
|
88
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
89
|
-
chunk5HJFQVUR_js.Button,
|
|
90
|
-
{
|
|
91
|
-
variant: canGenerate ? "default" : "secondary",
|
|
92
|
-
size: "sm",
|
|
93
|
-
onClick: onGenerate,
|
|
94
|
-
disabled: !canGenerate,
|
|
95
|
-
children: [
|
|
96
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-4 w-4 fill-current" }),
|
|
97
|
-
"Generate"
|
|
98
|
-
]
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
] }),
|
|
102
|
-
[hasOutput, isProcessing, canGenerate, onGenerate, onStop, onExpand]
|
|
103
|
-
);
|
|
104
|
-
return { titleElement, headerActions };
|
|
105
|
-
}
|
|
106
|
-
function useAutoLoadModelSchema({
|
|
107
|
-
currentModel,
|
|
108
|
-
selectedModel,
|
|
109
|
-
modelIdMap,
|
|
110
|
-
onModelSelect
|
|
111
|
-
}) {
|
|
112
|
-
const { modelSchema } = chunkRJ262NXS_js.useWorkflowUIConfig();
|
|
113
|
-
const hasAttemptedSchemaLoad = react.useRef(false);
|
|
114
|
-
react.useEffect(() => {
|
|
115
|
-
if (hasAttemptedSchemaLoad.current || selectedModel || !currentModel || !modelSchema) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const modelId = modelIdMap[currentModel];
|
|
119
|
-
if (!modelId) return;
|
|
120
|
-
const controller = new AbortController();
|
|
121
|
-
let isCancelled = false;
|
|
122
|
-
const loadSchema = async () => {
|
|
123
|
-
try {
|
|
124
|
-
const model = await modelSchema.fetchModelSchema(modelId, controller.signal);
|
|
125
|
-
if (model && !isCancelled) {
|
|
126
|
-
hasAttemptedSchemaLoad.current = true;
|
|
127
|
-
onModelSelect(model);
|
|
128
|
-
}
|
|
129
|
-
} catch {
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
loadSchema();
|
|
133
|
-
return () => {
|
|
134
|
-
isCancelled = true;
|
|
135
|
-
controller.abort();
|
|
136
|
-
};
|
|
137
|
-
}, [currentModel, selectedModel, modelIdMap, onModelSelect, modelSchema]);
|
|
138
|
-
}
|
|
139
|
-
function useRequiredInputs(nodeId, nodeType) {
|
|
140
|
-
const edges = chunkIHF35QZD_js.useWorkflowStore((state) => state.edges);
|
|
141
|
-
return react.useMemo(() => {
|
|
142
|
-
const nodeDef = types.NODE_DEFINITIONS[nodeType];
|
|
143
|
-
if (!nodeDef) {
|
|
144
|
-
return { hasRequiredInputs: true, missingInputs: [], connectionStatus: /* @__PURE__ */ new Map() };
|
|
145
|
-
}
|
|
146
|
-
const incomingEdges = edges.filter((e) => e.target === nodeId);
|
|
147
|
-
const connectedHandles = new Set(incomingEdges.map((e) => e.targetHandle).filter(Boolean));
|
|
148
|
-
const connectionStatus = /* @__PURE__ */ new Map();
|
|
149
|
-
const missingInputs = [];
|
|
150
|
-
for (const input of nodeDef.inputs) {
|
|
151
|
-
const isConnected = connectedHandles.has(input.id);
|
|
152
|
-
connectionStatus.set(input.id, isConnected);
|
|
153
|
-
if (input.required && !isConnected) {
|
|
154
|
-
missingInputs.push(input.id);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return {
|
|
158
|
-
hasRequiredInputs: missingInputs.length === 0,
|
|
159
|
-
missingInputs,
|
|
160
|
-
connectionStatus
|
|
161
|
-
};
|
|
162
|
-
}, [nodeId, nodeType, edges]);
|
|
163
|
-
}
|
|
164
|
-
function extractOutputValue(node, handleType) {
|
|
165
|
-
const data = node.data;
|
|
166
|
-
if (handleType === "text") {
|
|
167
|
-
return data.outputText ?? data.prompt;
|
|
168
|
-
} else if (handleType === "image") {
|
|
169
|
-
return data.outputImage ?? data.image;
|
|
170
|
-
} else if (handleType === "video") {
|
|
171
|
-
return data.outputVideo ?? data.video;
|
|
172
|
-
} else if (handleType === "audio") {
|
|
173
|
-
return data.outputAudio ?? data.audio;
|
|
174
|
-
}
|
|
175
|
-
return void 0;
|
|
176
|
-
}
|
|
177
|
-
function useCanGenerate({
|
|
178
|
-
nodeId,
|
|
179
|
-
nodeType,
|
|
180
|
-
inputSchema,
|
|
181
|
-
schemaParams
|
|
182
|
-
}) {
|
|
183
|
-
const { hasRequiredInputs, missingInputs } = useRequiredInputs(nodeId, nodeType);
|
|
184
|
-
const getConnectedInputs = chunkIHF35QZD_js.useWorkflowStore((state) => state.getConnectedInputs);
|
|
185
|
-
const incomingEdgesSelector = react.useCallback(
|
|
186
|
-
(state) => state.edges.filter((e) => e.target === nodeId),
|
|
187
|
-
[nodeId]
|
|
188
|
-
);
|
|
189
|
-
const incomingEdges = chunkIHF35QZD_js.useWorkflowStore(shallow.useShallow(incomingEdgesSelector));
|
|
190
|
-
const connectedOutputsSelector = react.useCallback(
|
|
191
|
-
(state) => {
|
|
192
|
-
const outputs = {};
|
|
193
|
-
for (const edge of incomingEdges) {
|
|
194
|
-
const sourceNode = state.nodes.find((n) => n.id === edge.source);
|
|
195
|
-
if (sourceNode) {
|
|
196
|
-
outputs[edge.source] = extractOutputValue(sourceNode, edge.sourceHandle);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return outputs;
|
|
200
|
-
},
|
|
201
|
-
[incomingEdges]
|
|
202
|
-
);
|
|
203
|
-
chunkIHF35QZD_js.useWorkflowStore(shallow.useShallow(connectedOutputsSelector));
|
|
204
|
-
return react.useMemo(() => {
|
|
205
|
-
const missingItems = [];
|
|
206
|
-
for (const inputId of missingInputs) {
|
|
207
|
-
missingItems.push({
|
|
208
|
-
type: "connection",
|
|
209
|
-
field: inputId,
|
|
210
|
-
message: `Missing connection: ${inputId}`
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
const connectedInputs = getConnectedInputs(nodeId);
|
|
214
|
-
const nodeDef = types.NODE_DEFINITIONS[nodeType];
|
|
215
|
-
const requiredHandleIds = new Set(
|
|
216
|
-
nodeDef?.inputs.filter((h) => h.required).map((h) => h.id) ?? []
|
|
217
|
-
);
|
|
218
|
-
let hasRequiredData = true;
|
|
219
|
-
let hasConnectedData = true;
|
|
220
|
-
if (hasRequiredInputs) {
|
|
221
|
-
for (const edge of incomingEdges) {
|
|
222
|
-
const handleId = edge.targetHandle;
|
|
223
|
-
if (!handleId) continue;
|
|
224
|
-
if (!connectedInputs.has(handleId)) {
|
|
225
|
-
hasConnectedData = false;
|
|
226
|
-
if (requiredHandleIds.has(handleId)) {
|
|
227
|
-
hasRequiredData = false;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
const schemaValidation = chunkEMUMKW5C_js.validateRequiredSchemaFields(
|
|
233
|
-
inputSchema,
|
|
234
|
-
schemaParams ?? {},
|
|
235
|
-
chunkEMUMKW5C_js.CONNECTION_FIELDS
|
|
236
|
-
);
|
|
237
|
-
for (const field of schemaValidation.missingFields) {
|
|
238
|
-
missingItems.push({
|
|
239
|
-
type: "schema",
|
|
240
|
-
field,
|
|
241
|
-
message: `Required field: ${field}`
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
const canGenerate = hasRequiredInputs && hasRequiredData && schemaValidation.isValid;
|
|
245
|
-
return {
|
|
246
|
-
canGenerate,
|
|
247
|
-
missingItems,
|
|
248
|
-
hasRequiredConnections: hasRequiredInputs,
|
|
249
|
-
hasConnectedData,
|
|
250
|
-
hasRequiredSchemaFields: schemaValidation.isValid
|
|
251
|
-
};
|
|
252
|
-
}, [
|
|
253
|
-
nodeId,
|
|
254
|
-
nodeType,
|
|
255
|
-
hasRequiredInputs,
|
|
256
|
-
missingInputs,
|
|
257
|
-
inputSchema,
|
|
258
|
-
schemaParams,
|
|
259
|
-
getConnectedInputs,
|
|
260
|
-
incomingEdges
|
|
261
|
-
]);
|
|
262
|
-
}
|
|
263
|
-
function useModelSelection({ nodeId, modelMap, fallbackModel }) {
|
|
264
|
-
const updateNodeData = chunkIHF35QZD_js.useWorkflowStore((state) => state.updateNodeData);
|
|
265
|
-
const handleModelSelect = react.useCallback(
|
|
266
|
-
(model) => {
|
|
267
|
-
const internalModel = modelMap[model.id] ?? fallbackModel;
|
|
268
|
-
const schemaDefaults = chunkEMUMKW5C_js.getSchemaDefaults(model.inputSchema);
|
|
269
|
-
const selectedModel = {
|
|
270
|
-
provider: model.provider,
|
|
271
|
-
modelId: model.id,
|
|
272
|
-
displayName: model.displayName,
|
|
273
|
-
inputSchema: model.inputSchema,
|
|
274
|
-
componentSchemas: model.componentSchemas
|
|
275
|
-
};
|
|
276
|
-
updateNodeData(nodeId, {
|
|
277
|
-
model: internalModel,
|
|
278
|
-
provider: model.provider,
|
|
279
|
-
selectedModel,
|
|
280
|
-
schemaParams: schemaDefaults
|
|
281
|
-
});
|
|
282
|
-
},
|
|
283
|
-
[nodeId, modelMap, fallbackModel, updateNodeData]
|
|
284
|
-
);
|
|
285
|
-
return { handleModelSelect };
|
|
286
|
-
}
|
|
287
|
-
function useNodeExecution(nodeId) {
|
|
288
|
-
const updateNodeData = chunkIHF35QZD_js.useWorkflowStore((state) => state.updateNodeData);
|
|
289
|
-
const executeNode = chunkAXFOCPPP_js.useExecutionStore((state) => state.executeNode);
|
|
290
|
-
const stopNodeExecution = chunkAXFOCPPP_js.useExecutionStore((state) => state.stopNodeExecution);
|
|
291
|
-
const handleGenerate = react.useCallback(() => {
|
|
292
|
-
updateNodeData(nodeId, { status: types.NodeStatusEnum.PROCESSING });
|
|
293
|
-
executeNode(nodeId);
|
|
294
|
-
}, [nodeId, executeNode, updateNodeData]);
|
|
295
|
-
const handleStop = react.useCallback(() => {
|
|
296
|
-
stopNodeExecution(nodeId);
|
|
297
|
-
}, [nodeId, stopNodeExecution]);
|
|
298
|
-
return { handleGenerate, handleStop };
|
|
299
|
-
}
|
|
300
|
-
function readFileAsBase64(file, nodeId, getMetadata, buildUploadUpdate, updateNodeData, onComplete) {
|
|
301
|
-
const reader = new FileReader();
|
|
302
|
-
reader.onload = async (event) => {
|
|
303
|
-
const dataUrl = event.target?.result;
|
|
304
|
-
const metadata = await getMetadata(dataUrl);
|
|
305
|
-
updateNodeData(nodeId, buildUploadUpdate(dataUrl, file.name, metadata));
|
|
306
|
-
};
|
|
307
|
-
reader.readAsDataURL(file);
|
|
308
|
-
}
|
|
309
|
-
function useMediaUpload({
|
|
310
|
-
nodeId,
|
|
311
|
-
mediaType,
|
|
312
|
-
initialUrl = "",
|
|
313
|
-
getMetadata,
|
|
314
|
-
buildUploadUpdate,
|
|
315
|
-
buildUrlUpdate,
|
|
316
|
-
buildRemoveUpdate
|
|
317
|
-
}) {
|
|
318
|
-
const updateNodeData = chunkIHF35QZD_js.useWorkflowStore((state) => state.updateNodeData);
|
|
319
|
-
const workflowId = chunkIHF35QZD_js.useWorkflowStore((state) => state.workflowId);
|
|
320
|
-
const { fileUpload } = chunkRJ262NXS_js.useWorkflowUIConfig();
|
|
321
|
-
const fileInputRef = react.useRef(null);
|
|
322
|
-
const [showUrlInput, setShowUrlInput] = react.useState(false);
|
|
323
|
-
const [urlValue, setUrlValue] = react.useState(initialUrl);
|
|
324
|
-
const [isUploading, setIsUploading] = react.useState(false);
|
|
325
|
-
const getMetadataRef = react.useRef(getMetadata);
|
|
326
|
-
getMetadataRef.current = getMetadata;
|
|
327
|
-
const buildUploadUpdateRef = react.useRef(buildUploadUpdate);
|
|
328
|
-
buildUploadUpdateRef.current = buildUploadUpdate;
|
|
329
|
-
const buildUrlUpdateRef = react.useRef(buildUrlUpdate);
|
|
330
|
-
buildUrlUpdateRef.current = buildUrlUpdate;
|
|
331
|
-
const buildRemoveUpdateRef = react.useRef(buildRemoveUpdate);
|
|
332
|
-
buildRemoveUpdateRef.current = buildRemoveUpdate;
|
|
333
|
-
const handleFileSelect = react.useCallback(
|
|
334
|
-
async (e) => {
|
|
335
|
-
const file = e.target.files?.[0];
|
|
336
|
-
if (!file) return;
|
|
337
|
-
if (workflowId && fileUpload) {
|
|
338
|
-
setIsUploading(true);
|
|
339
|
-
try {
|
|
340
|
-
const result = await fileUpload.uploadFile(
|
|
341
|
-
`/files/workflows/${workflowId}/input/${mediaType}`,
|
|
342
|
-
file
|
|
343
|
-
);
|
|
344
|
-
const metadata = await getMetadataRef.current(result.url);
|
|
345
|
-
updateNodeData(
|
|
346
|
-
nodeId,
|
|
347
|
-
buildUploadUpdateRef.current(result.url, result.filename, metadata)
|
|
348
|
-
);
|
|
349
|
-
} catch (_error) {
|
|
350
|
-
readFileAsBase64(
|
|
351
|
-
file,
|
|
352
|
-
nodeId,
|
|
353
|
-
getMetadataRef.current,
|
|
354
|
-
buildUploadUpdateRef.current,
|
|
355
|
-
updateNodeData
|
|
356
|
-
);
|
|
357
|
-
} finally {
|
|
358
|
-
setIsUploading(false);
|
|
359
|
-
}
|
|
360
|
-
} else {
|
|
361
|
-
readFileAsBase64(
|
|
362
|
-
file,
|
|
363
|
-
nodeId,
|
|
364
|
-
getMetadataRef.current,
|
|
365
|
-
buildUploadUpdateRef.current,
|
|
366
|
-
updateNodeData
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
},
|
|
370
|
-
[nodeId, updateNodeData, workflowId, mediaType, fileUpload]
|
|
371
|
-
);
|
|
372
|
-
const handleRemove = react.useCallback(() => {
|
|
373
|
-
updateNodeData(nodeId, buildRemoveUpdateRef.current());
|
|
374
|
-
setUrlValue("");
|
|
375
|
-
}, [nodeId, updateNodeData]);
|
|
376
|
-
const handleUrlSubmit = react.useCallback(async () => {
|
|
377
|
-
if (!urlValue.trim()) return;
|
|
378
|
-
try {
|
|
379
|
-
let metadata;
|
|
380
|
-
if (mediaType === "image") {
|
|
381
|
-
metadata = await chunkEMUMKW5C_js.getImageDimensions(urlValue);
|
|
382
|
-
} else {
|
|
383
|
-
const meta = await chunkEMUMKW5C_js.getVideoMetadata(urlValue);
|
|
384
|
-
metadata = {
|
|
385
|
-
duration: meta.duration,
|
|
386
|
-
width: meta.dimensions.width,
|
|
387
|
-
height: meta.dimensions.height
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
updateNodeData(nodeId, buildUrlUpdateRef.current(urlValue, metadata));
|
|
391
|
-
} catch (_error) {
|
|
392
|
-
updateNodeData(nodeId, buildUrlUpdateRef.current(urlValue, null));
|
|
393
|
-
}
|
|
394
|
-
setShowUrlInput(false);
|
|
395
|
-
}, [nodeId, updateNodeData, urlValue, mediaType]);
|
|
396
|
-
const handleUrlKeyDown = react.useCallback(
|
|
397
|
-
(e) => {
|
|
398
|
-
if (e.key === "Enter") {
|
|
399
|
-
handleUrlSubmit();
|
|
400
|
-
} else if (e.key === "Escape") {
|
|
401
|
-
setShowUrlInput(false);
|
|
402
|
-
setUrlValue(initialUrl);
|
|
403
|
-
}
|
|
404
|
-
},
|
|
405
|
-
[handleUrlSubmit, initialUrl]
|
|
406
|
-
);
|
|
407
|
-
return {
|
|
408
|
-
fileInputRef,
|
|
409
|
-
showUrlInput,
|
|
410
|
-
setShowUrlInput,
|
|
411
|
-
urlValue,
|
|
412
|
-
setUrlValue,
|
|
413
|
-
isUploading,
|
|
414
|
-
handleFileSelect,
|
|
415
|
-
handleRemove,
|
|
416
|
-
handleUrlSubmit,
|
|
417
|
-
handleUrlKeyDown
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
function usePromptAutocomplete({
|
|
421
|
-
availableVariables,
|
|
422
|
-
textareaRef,
|
|
423
|
-
localTemplate,
|
|
424
|
-
setLocalTemplate,
|
|
425
|
-
onTemplateCommit
|
|
426
|
-
}) {
|
|
427
|
-
const [showAutocomplete, setShowAutocomplete] = react.useState(false);
|
|
428
|
-
const [autocompletePosition, setAutocompletePosition] = react.useState({ top: 0, left: 0 });
|
|
429
|
-
const [autocompleteFilter, setAutocompleteFilter] = react.useState("");
|
|
430
|
-
const [selectedAutocompleteIndex, setSelectedAutocompleteIndex] = react.useState(0);
|
|
431
|
-
const filteredAutocompleteVars = react.useMemo(() => {
|
|
432
|
-
return availableVariables.filter(
|
|
433
|
-
(v) => v.name.toLowerCase().includes(autocompleteFilter.toLowerCase())
|
|
434
|
-
);
|
|
435
|
-
}, [availableVariables, autocompleteFilter]);
|
|
436
|
-
const handleAutocompleteSelect = react.useCallback(
|
|
437
|
-
(varName) => {
|
|
438
|
-
if (!textareaRef.current) return;
|
|
439
|
-
const cursorPos = textareaRef.current.selectionStart;
|
|
440
|
-
const textBeforeCursor = localTemplate.slice(0, cursorPos);
|
|
441
|
-
const textAfterCursor = localTemplate.slice(cursorPos);
|
|
442
|
-
const match = textBeforeCursor.match(/@(\w*)$/);
|
|
443
|
-
if (!match) return;
|
|
444
|
-
const atPosition = cursorPos - match[0].length;
|
|
445
|
-
const newTemplate = `${localTemplate.slice(0, atPosition)}@${varName}${textAfterCursor}`;
|
|
446
|
-
setLocalTemplate(newTemplate);
|
|
447
|
-
onTemplateCommit?.(newTemplate);
|
|
448
|
-
setShowAutocomplete(false);
|
|
449
|
-
const newCursorPos = atPosition + varName.length + 1;
|
|
450
|
-
setTimeout(() => {
|
|
451
|
-
if (textareaRef.current) {
|
|
452
|
-
textareaRef.current.focus();
|
|
453
|
-
textareaRef.current.setSelectionRange(newCursorPos, newCursorPos);
|
|
454
|
-
}
|
|
455
|
-
}, 0);
|
|
456
|
-
},
|
|
457
|
-
[localTemplate, textareaRef, setLocalTemplate, onTemplateCommit]
|
|
458
|
-
);
|
|
459
|
-
const handleChange = react.useCallback(
|
|
460
|
-
(e) => {
|
|
461
|
-
const newValue = e.target.value;
|
|
462
|
-
setLocalTemplate(newValue);
|
|
463
|
-
const cursorPos = e.target.selectionStart;
|
|
464
|
-
const textBeforeCursor = newValue.slice(0, cursorPos);
|
|
465
|
-
const match = textBeforeCursor.match(/@(\w*)$/);
|
|
466
|
-
if (match && textareaRef.current) {
|
|
467
|
-
setAutocompleteFilter(match[1] || "");
|
|
468
|
-
setSelectedAutocompleteIndex(0);
|
|
469
|
-
const lineHeight = 20;
|
|
470
|
-
const lines = textBeforeCursor.split("\n");
|
|
471
|
-
const currentLine = lines.length - 1;
|
|
472
|
-
const top = currentLine * lineHeight + 30;
|
|
473
|
-
const left = 10;
|
|
474
|
-
setAutocompletePosition({ top, left });
|
|
475
|
-
setShowAutocomplete(true);
|
|
476
|
-
} else {
|
|
477
|
-
setShowAutocomplete(false);
|
|
478
|
-
}
|
|
479
|
-
},
|
|
480
|
-
[textareaRef, setLocalTemplate]
|
|
481
|
-
);
|
|
482
|
-
const handleKeyDown = react.useCallback(
|
|
483
|
-
(e) => {
|
|
484
|
-
if (!showAutocomplete) return;
|
|
485
|
-
if (e.key === "ArrowDown") {
|
|
486
|
-
e.preventDefault();
|
|
487
|
-
setSelectedAutocompleteIndex((prev) => (prev + 1) % filteredAutocompleteVars.length);
|
|
488
|
-
} else if (e.key === "ArrowUp") {
|
|
489
|
-
e.preventDefault();
|
|
490
|
-
setSelectedAutocompleteIndex(
|
|
491
|
-
(prev) => (prev - 1 + filteredAutocompleteVars.length) % filteredAutocompleteVars.length
|
|
492
|
-
);
|
|
493
|
-
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
494
|
-
if (filteredAutocompleteVars.length > 0) {
|
|
495
|
-
e.preventDefault();
|
|
496
|
-
handleAutocompleteSelect(filteredAutocompleteVars[selectedAutocompleteIndex].name);
|
|
497
|
-
}
|
|
498
|
-
} else if (e.key === "Escape") {
|
|
499
|
-
e.preventDefault();
|
|
500
|
-
e.stopPropagation();
|
|
501
|
-
setShowAutocomplete(false);
|
|
502
|
-
}
|
|
503
|
-
},
|
|
504
|
-
[
|
|
505
|
-
showAutocomplete,
|
|
506
|
-
filteredAutocompleteVars,
|
|
507
|
-
selectedAutocompleteIndex,
|
|
508
|
-
handleAutocompleteSelect
|
|
509
|
-
]
|
|
510
|
-
);
|
|
511
|
-
const closeAutocomplete = react.useCallback(() => {
|
|
512
|
-
setShowAutocomplete(false);
|
|
513
|
-
}, []);
|
|
514
|
-
return {
|
|
515
|
-
showAutocomplete,
|
|
516
|
-
autocompletePosition,
|
|
517
|
-
filteredAutocompleteVars,
|
|
518
|
-
selectedAutocompleteIndex,
|
|
519
|
-
handleChange,
|
|
520
|
-
handleKeyDown,
|
|
521
|
-
handleAutocompleteSelect,
|
|
522
|
-
closeAutocomplete
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
exports.useAIGenNode = useAIGenNode;
|
|
527
|
-
exports.useAIGenNodeHeader = useAIGenNodeHeader;
|
|
528
|
-
exports.useAutoLoadModelSchema = useAutoLoadModelSchema;
|
|
529
|
-
exports.useCanGenerate = useCanGenerate;
|
|
530
|
-
exports.useMediaUpload = useMediaUpload;
|
|
531
|
-
exports.useModelSelection = useModelSelection;
|
|
532
|
-
exports.useNodeExecution = useNodeExecution;
|
|
533
|
-
exports.usePromptAutocomplete = usePromptAutocomplete;
|
|
534
|
-
exports.useRequiredInputs = useRequiredInputs;
|