bizydraft 0.1.30__py3-none-any.whl → 0.2.1__py3-none-any.whl
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.
Potentially problematic release.
This version of bizydraft might be problematic. Click here for more details.
- bizydraft/block_nodes.py +35 -0
- bizydraft/env.py +11 -0
- bizydraft/hijack_nodes.py +66 -6
- bizydraft/hijack_routes.py +87 -184
- bizydraft/oss_utils.py +227 -0
- bizydraft/patch_handlers.py +150 -0
- bizydraft/postload.py +26 -8
- bizydraft/static/js/aiAppHandler.js +540 -0
- bizydraft/static/js/freezeModeHandler.js +490 -0
- bizydraft/static/js/handleStyle.js +7 -3
- bizydraft/static/js/hookLoadImage.js +121 -81
- bizydraft/static/js/hookLoadModel.js +152 -0
- bizydraft/static/js/main.js +0 -1
- bizydraft/static/js/nodeFocusHandler.js +153 -0
- bizydraft/static/js/nodeParamsFilter.js +136 -0
- bizydraft/static/js/postEvent.js +291 -61
- bizydraft/static/js/tool.js +60 -0
- bizydraft/workflow_io.py +2 -2
- {bizydraft-0.1.30.dist-info → bizydraft-0.2.1.dist-info}/METADATA +1 -1
- bizydraft-0.2.1.dist-info/RECORD +28 -0
- bizydraft-0.1.30.dist-info/RECORD +0 -19
- {bizydraft-0.1.30.dist-info → bizydraft-0.2.1.dist-info}/WHEEL +0 -0
- {bizydraft-0.1.30.dist-info → bizydraft-0.2.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 节点参数过滤工具
|
|
3
|
+
* 用于处理节点参数在发布模式下的过滤
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// 存储从服务端获取的节点参数信息
|
|
7
|
+
let nodeParamsMap = new Map();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 设置节点参数映射
|
|
11
|
+
* @param {Array} inputsData - 服务端返回的inputs数组
|
|
12
|
+
*/
|
|
13
|
+
function setNodeParams(inputsData) {
|
|
14
|
+
if (!Array.isArray(inputsData)) {
|
|
15
|
+
console.error('Invalid inputs data format:', inputsData);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 清空现有映射
|
|
20
|
+
nodeParamsMap.clear();
|
|
21
|
+
|
|
22
|
+
// 构建新的映射
|
|
23
|
+
inputsData.forEach(nodeInfo => {
|
|
24
|
+
if (nodeInfo && nodeInfo.nodeId && Array.isArray(nodeInfo.params)) {
|
|
25
|
+
// 以nodeId为键,存储参数信息
|
|
26
|
+
const paramNames = nodeInfo.params.map(param => param.name);
|
|
27
|
+
nodeParamsMap.set(nodeInfo.nodeId, {
|
|
28
|
+
name: nodeInfo.name,
|
|
29
|
+
displayName: nodeInfo.displayName,
|
|
30
|
+
paramNames: paramNames,
|
|
31
|
+
params: nodeInfo.params
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
console.log('节点参数映射已更新:', nodeParamsMap);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 过滤节点参数
|
|
41
|
+
* @param {Object} node - 节点对象
|
|
42
|
+
* @returns {Object|null} - 过滤后的节点信息,如果节点不符合条件则返回null
|
|
43
|
+
*/
|
|
44
|
+
function filterNodeWidgets(node) {
|
|
45
|
+
if (!node || !node.id) return null;
|
|
46
|
+
|
|
47
|
+
// 如果节点ID不在参数映射中,则不是可配置节点
|
|
48
|
+
if (!nodeParamsMap.has(String(node.id))) {
|
|
49
|
+
console.log(`节点 ${node.id} 不在可配置列表中`);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 获取节点的允许参数列表
|
|
54
|
+
const nodeParamsInfo = nodeParamsMap.get(String(node.id));
|
|
55
|
+
const allowedParamNames = nodeParamsInfo.paramNames;
|
|
56
|
+
|
|
57
|
+
// 提取节点信息
|
|
58
|
+
const nodeInfo = {
|
|
59
|
+
id: node.id,
|
|
60
|
+
type: node.type,
|
|
61
|
+
comfyClass: node.comfyClass,
|
|
62
|
+
title: node.title || nodeParamsInfo.displayName,
|
|
63
|
+
widgets: []
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// 过滤widgets,只保留在allowedParamNames中的widget
|
|
67
|
+
if (node.widgets && node.widgets.length > 0) {
|
|
68
|
+
nodeInfo.widgets = node.widgets
|
|
69
|
+
.filter(widget => {
|
|
70
|
+
return widget.type !== "hidden" &&
|
|
71
|
+
!widget.disabled &&
|
|
72
|
+
allowedParamNames.includes(String(widget.name));
|
|
73
|
+
})
|
|
74
|
+
.map(widget => {
|
|
75
|
+
const widgetInfo = {
|
|
76
|
+
name: String(widget.name || ""),
|
|
77
|
+
value: widget.value != null ? widget.value : "",
|
|
78
|
+
type: String(widget.type || "")
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// 处理options属性
|
|
82
|
+
if (widget.options && widget.options.values) {
|
|
83
|
+
widgetInfo.options = { values: [] };
|
|
84
|
+
|
|
85
|
+
if (Array.isArray(widget.options.values)) {
|
|
86
|
+
widgetInfo.options.values = [...widget.options.values];
|
|
87
|
+
} else if (typeof widget.options.values === 'function') {
|
|
88
|
+
try {
|
|
89
|
+
const values = widget.options.values();
|
|
90
|
+
if (Array.isArray(values)) {
|
|
91
|
+
widgetInfo.options.values = [...values];
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
// 忽略错误
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return widgetInfo;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 如果过滤后没有可配置的参数,则不符合条件
|
|
104
|
+
if (nodeInfo.widgets.length === 0) {
|
|
105
|
+
console.log(`节点 ${node.id} 没有可配置的参数`);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return nodeInfo;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 检查节点是否可配置
|
|
114
|
+
* @param {number|string} nodeId - 节点ID
|
|
115
|
+
* @returns {boolean} - 节点是否可配置
|
|
116
|
+
*/
|
|
117
|
+
function isConfigurableNode(nodeId) {
|
|
118
|
+
return nodeParamsMap.has(String(nodeId));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 获取节点原始参数信息
|
|
123
|
+
* @param {number|string} nodeId - 节点ID
|
|
124
|
+
* @returns {Object|null} - 节点参数信息
|
|
125
|
+
*/
|
|
126
|
+
function getNodeParamsInfo(nodeId) {
|
|
127
|
+
return nodeParamsMap.get(String(nodeId)) || null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 导出模块
|
|
131
|
+
export {
|
|
132
|
+
setNodeParams,
|
|
133
|
+
filterNodeWidgets,
|
|
134
|
+
isConfigurableNode,
|
|
135
|
+
getNodeParamsInfo
|
|
136
|
+
};
|
bizydraft/static/js/postEvent.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { app } from "../../scripts/app.js";
|
|
2
|
+
import { enableAIAppMode, disableAIAppMode, selectInputNode, deselectInputNode, updateInputNodeWidget, getSelectedInputNodes, clearSelectedInputNodes, toggleExportMode } from "./aiAppHandler.js";
|
|
3
|
+
import { focusNodeOnly } from "./nodeFocusHandler.js";
|
|
2
4
|
|
|
3
5
|
app.registerExtension({
|
|
4
6
|
name: "comfy.BizyAir.Socket",
|
|
@@ -184,8 +186,15 @@ app.registerExtension({
|
|
|
184
186
|
method: 'progress_info_change',
|
|
185
187
|
result: msg.progress_info
|
|
186
188
|
}, '*');
|
|
187
|
-
|
|
188
189
|
switch (msg.type) {
|
|
190
|
+
case 'load_start':
|
|
191
|
+
case 'load_end':
|
|
192
|
+
case 'prompt_id':
|
|
193
|
+
window.parent.postMessage({
|
|
194
|
+
type: 'functionResult',
|
|
195
|
+
method: 'preparingStatus',
|
|
196
|
+
result: msg
|
|
197
|
+
}, '*')
|
|
189
198
|
case 'status':
|
|
190
199
|
if (msg.data.sid) {
|
|
191
200
|
const clientId = msg.data.sid;
|
|
@@ -209,6 +218,17 @@ app.registerExtension({
|
|
|
209
218
|
}
|
|
210
219
|
dispatchCustomEvent(msg.type, msg.data);
|
|
211
220
|
break;
|
|
221
|
+
case 'error':
|
|
222
|
+
self.taskRunning = false;
|
|
223
|
+
dispatchCustomEvent('execution_error', {
|
|
224
|
+
exception_message: msg.data.error_message || 'Unknown error',
|
|
225
|
+
traceback: ['Manual error triggered'],
|
|
226
|
+
executed: [],
|
|
227
|
+
prompt_id: 'manual',
|
|
228
|
+
node_id: '0',
|
|
229
|
+
node_type: 'RunError',
|
|
230
|
+
});
|
|
231
|
+
break;
|
|
212
232
|
case 'execution_error':
|
|
213
233
|
case 'execution_interrupted':
|
|
214
234
|
self.taskRunning = false;
|
|
@@ -411,14 +431,11 @@ app.registerExtension({
|
|
|
411
431
|
|
|
412
432
|
async setup() {
|
|
413
433
|
const createSocket = this.createSocket.bind(this);
|
|
414
|
-
const getSocket = this.getSocket.bind(this);
|
|
415
|
-
const getSocketAsync = this.getSocketAsync.bind(this);
|
|
416
434
|
const closeSocket = this.closeSocket.bind(this);
|
|
417
|
-
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const stopPing = this.stopPing.bind(this);
|
|
435
|
+
|
|
436
|
+
const customErrorStyles = new Map()
|
|
437
|
+
|
|
438
|
+
|
|
422
439
|
|
|
423
440
|
// 方法映射
|
|
424
441
|
const methods = {
|
|
@@ -432,26 +449,6 @@ app.registerExtension({
|
|
|
432
449
|
return socket;
|
|
433
450
|
},
|
|
434
451
|
|
|
435
|
-
startSocket: async function (params) {
|
|
436
|
-
try {
|
|
437
|
-
const socket = await getSocketAsync(params.url);
|
|
438
|
-
window.parent.postMessage({
|
|
439
|
-
type: 'functionResult',
|
|
440
|
-
method: 'startSocket',
|
|
441
|
-
result: 'Socket连接已启动'
|
|
442
|
-
}, '*');
|
|
443
|
-
return socket;
|
|
444
|
-
} catch (error) {
|
|
445
|
-
window.parent.postMessage({
|
|
446
|
-
type: 'functionResult',
|
|
447
|
-
method: 'startSocket',
|
|
448
|
-
result: 'Socket连接失败: ' + error.message,
|
|
449
|
-
error: true
|
|
450
|
-
}, '*');
|
|
451
|
-
return null;
|
|
452
|
-
}
|
|
453
|
-
},
|
|
454
|
-
|
|
455
452
|
closeSocket: function () {
|
|
456
453
|
const result = closeSocket();
|
|
457
454
|
window.parent.postMessage({
|
|
@@ -462,34 +459,6 @@ app.registerExtension({
|
|
|
462
459
|
return result;
|
|
463
460
|
},
|
|
464
461
|
|
|
465
|
-
changeSocketUrl: function (params) {
|
|
466
|
-
if (!params.url) {
|
|
467
|
-
console.error('缺少url参数');
|
|
468
|
-
return false;
|
|
469
|
-
}
|
|
470
|
-
const socket = changeSocketUrl(params.url);
|
|
471
|
-
window.parent.postMessage({
|
|
472
|
-
type: 'functionResult',
|
|
473
|
-
method: 'changeSocketUrl',
|
|
474
|
-
result: 'Socket URL已更改为' + params.url
|
|
475
|
-
}, '*');
|
|
476
|
-
return socket;
|
|
477
|
-
},
|
|
478
|
-
|
|
479
|
-
sendSocketMessage: async function (params) {
|
|
480
|
-
if (!params.message) {
|
|
481
|
-
console.error('缺少message参数');
|
|
482
|
-
return false;
|
|
483
|
-
}
|
|
484
|
-
const result = await sendSocketMessage(params.message);
|
|
485
|
-
window.parent.postMessage({
|
|
486
|
-
type: 'functionResult',
|
|
487
|
-
method: 'sendSocketMessage',
|
|
488
|
-
result: result ? '消息发送成功' : '消息发送失败'
|
|
489
|
-
}, '*');
|
|
490
|
-
return result;
|
|
491
|
-
},
|
|
492
|
-
|
|
493
462
|
clearCanvas: function () {
|
|
494
463
|
app.graph.clear();
|
|
495
464
|
window.parent.postMessage({
|
|
@@ -499,11 +468,10 @@ app.registerExtension({
|
|
|
499
468
|
}, '*');
|
|
500
469
|
return true;
|
|
501
470
|
},
|
|
502
|
-
|
|
503
471
|
loadWorkflow: function (params) {
|
|
504
472
|
app.graph.clear();
|
|
505
473
|
document.dispatchEvent(new CustomEvent('workflowLoaded', {
|
|
506
|
-
detail: params
|
|
474
|
+
detail: params.json
|
|
507
475
|
}));
|
|
508
476
|
if (params.json.version) {
|
|
509
477
|
app.loadGraphData(params.json);
|
|
@@ -537,6 +505,19 @@ app.registerExtension({
|
|
|
537
505
|
}, '*');
|
|
538
506
|
return graph.workflow;
|
|
539
507
|
},
|
|
508
|
+
// 新增:获取 workflow 和 output
|
|
509
|
+
getWorkflowWithOutput: async function () {
|
|
510
|
+
const graph = await app.graphToPrompt();
|
|
511
|
+
window.parent.postMessage({
|
|
512
|
+
type: 'functionResult',
|
|
513
|
+
method: 'getWorkflowWithOutput',
|
|
514
|
+
result: {
|
|
515
|
+
workflow: graph.workflow,
|
|
516
|
+
output: graph.output
|
|
517
|
+
}
|
|
518
|
+
}, '*');
|
|
519
|
+
return { workflow: graph.workflow, output: graph.output };
|
|
520
|
+
},
|
|
540
521
|
saveApiJson: async function (params) {
|
|
541
522
|
const graph = await app.graphToPrompt();
|
|
542
523
|
window.parent.postMessage({
|
|
@@ -562,6 +543,7 @@ app.registerExtension({
|
|
|
562
543
|
|
|
563
544
|
const graph = await app.graphToPrompt();
|
|
564
545
|
const clientId = sessionStorage.getItem("clientId");
|
|
546
|
+
await app.queuePrompt(graph.output);
|
|
565
547
|
const resPrompt = await fetch("api/prompt", {
|
|
566
548
|
method: "POST",
|
|
567
549
|
body: JSON.stringify({
|
|
@@ -577,8 +559,45 @@ app.registerExtension({
|
|
|
577
559
|
});
|
|
578
560
|
const resPromptJson = await resPrompt.json();
|
|
579
561
|
if (resPromptJson.error) {
|
|
580
|
-
|
|
562
|
+
this.openCustomError({
|
|
563
|
+
nodeId: resPromptJson.node_id,
|
|
564
|
+
nodeType: resPromptJson.node_type,
|
|
565
|
+
errorMessage: resPromptJson.error,
|
|
566
|
+
borderColor: '#FF0000'
|
|
567
|
+
})
|
|
568
|
+
return
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
for (const i in resPromptJson.node_errors) {
|
|
572
|
+
|
|
573
|
+
if (resPromptJson.node_errors[i].errors) {
|
|
574
|
+
const err = resPromptJson.node_errors[i].errors[0]
|
|
575
|
+
if (err) return
|
|
576
|
+
this.openCustomError({
|
|
577
|
+
nodeId: i,
|
|
578
|
+
nodeType: err.type,
|
|
579
|
+
errorMessage: err.error,
|
|
580
|
+
borderColor: '#FF0000'
|
|
581
|
+
})
|
|
582
|
+
return
|
|
583
|
+
} else {
|
|
584
|
+
console.log(resPromptJson.node_errors[i])
|
|
585
|
+
}
|
|
581
586
|
}
|
|
587
|
+
|
|
588
|
+
if (Object.keys(resPromptJson.node_errors).length) return
|
|
589
|
+
graph.workflow.nodes.forEach(node => {
|
|
590
|
+
for (const key in graph.output) {
|
|
591
|
+
if (graph.output[key].class_type === node.type) {
|
|
592
|
+
if (!graph.output[key]._meta) {
|
|
593
|
+
graph.output[key]._meta = {};
|
|
594
|
+
}
|
|
595
|
+
graph.output[key]._meta.id = node.id;
|
|
596
|
+
break; // 找到匹配的就跳出循环
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
console.log(graph.output)
|
|
582
601
|
window.parent.postMessage({
|
|
583
602
|
type: 'functionResult',
|
|
584
603
|
method: 'runWorkflow',
|
|
@@ -611,7 +630,8 @@ app.registerExtension({
|
|
|
611
630
|
}
|
|
612
631
|
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
|
613
632
|
};
|
|
614
|
-
console.log("-----------setCookie-----------", params)
|
|
633
|
+
// console.log("-----------setCookie-----------", params)
|
|
634
|
+
// console.log("-----------setCookie-----------", params)
|
|
615
635
|
setCookie(params.name, params.value, params.days);
|
|
616
636
|
|
|
617
637
|
|
|
@@ -675,11 +695,13 @@ app.registerExtension({
|
|
|
675
695
|
return graph.workflow;
|
|
676
696
|
},
|
|
677
697
|
|
|
678
|
-
graphToPrompt: async function () {
|
|
698
|
+
graphToPrompt: async function (params) {
|
|
699
|
+
console.log('postEvent.js - graphToPrompt被调用,参数:', params);
|
|
679
700
|
const graph = await app.graphToPrompt();
|
|
680
701
|
window.parent.postMessage({
|
|
681
702
|
type: 'functionResult',
|
|
682
703
|
method: 'graphToPrompt',
|
|
704
|
+
params: params, // 传递原始参数
|
|
683
705
|
result: {
|
|
684
706
|
workflow: graph.workflow,
|
|
685
707
|
output: graph.output
|
|
@@ -703,8 +725,204 @@ app.registerExtension({
|
|
|
703
725
|
}, '*');
|
|
704
726
|
return true;
|
|
705
727
|
},
|
|
728
|
+
|
|
729
|
+
// AI应用相关方法
|
|
730
|
+
toggleAIAppMode: function(params) {
|
|
731
|
+
const enable = params.enable === true;
|
|
732
|
+
const result = enable ? enableAIAppMode() : disableAIAppMode();
|
|
733
|
+
window.parent.postMessage({
|
|
734
|
+
type: 'functionResult',
|
|
735
|
+
method: 'toggleAIAppMode',
|
|
736
|
+
result: result
|
|
737
|
+
}, '*');
|
|
738
|
+
return result;
|
|
739
|
+
},
|
|
740
|
+
|
|
741
|
+
selectInputNode: function(params) {
|
|
742
|
+
if (!params.nodeId) return false;
|
|
743
|
+
const result = selectInputNode(params.nodeId);
|
|
744
|
+
window.parent.postMessage({
|
|
745
|
+
type: 'functionResult',
|
|
746
|
+
method: 'selectInputNode',
|
|
747
|
+
result: result
|
|
748
|
+
}, '*');
|
|
749
|
+
return result;
|
|
750
|
+
},
|
|
751
|
+
|
|
752
|
+
selectExportNode: function(params) {
|
|
753
|
+
if (!params.nodeId) return false;
|
|
754
|
+
const result = selectInputNode(params.nodeId);
|
|
755
|
+
window.parent.postMessage({
|
|
756
|
+
type: 'functionResult',
|
|
757
|
+
method: 'selectExportNode',
|
|
758
|
+
result: result
|
|
759
|
+
}, '*');
|
|
760
|
+
return result;
|
|
761
|
+
},
|
|
762
|
+
|
|
763
|
+
deselectInputNode: function(params) {
|
|
764
|
+
if (!params.nodeId) return false;
|
|
765
|
+
const result = deselectInputNode(params.nodeId);
|
|
766
|
+
window.parent.postMessage({
|
|
767
|
+
type: 'functionResult',
|
|
768
|
+
method: 'deselectInputNode',
|
|
769
|
+
result: result
|
|
770
|
+
}, '*');
|
|
771
|
+
return result;
|
|
772
|
+
},
|
|
773
|
+
|
|
774
|
+
updateInputNodeWidget: function(params) {
|
|
775
|
+
if (!params.nodeId || params.widgetName === undefined) return false;
|
|
776
|
+
const result = updateInputNodeWidget(params.nodeId, params.widgetName, params.value);
|
|
777
|
+
window.parent.postMessage({
|
|
778
|
+
type: 'functionResult',
|
|
779
|
+
method: 'updateInputNodeWidget',
|
|
780
|
+
result: result
|
|
781
|
+
}, '*');
|
|
782
|
+
return result;
|
|
783
|
+
},
|
|
784
|
+
|
|
785
|
+
getInputNodes: function() {
|
|
786
|
+
const result = getSelectedInputNodes();
|
|
787
|
+
window.parent.postMessage({
|
|
788
|
+
type: 'functionResult',
|
|
789
|
+
method: 'getInputNodes',
|
|
790
|
+
result: result
|
|
791
|
+
}, '*');
|
|
792
|
+
return result;
|
|
793
|
+
},
|
|
794
|
+
|
|
795
|
+
clearInputNodes: function() {
|
|
796
|
+
const result = clearSelectedInputNodes();
|
|
797
|
+
window.parent.postMessage({
|
|
798
|
+
type: 'functionResult',
|
|
799
|
+
method: 'clearInputNodes',
|
|
800
|
+
result: result
|
|
801
|
+
}, '*');
|
|
802
|
+
return result;
|
|
803
|
+
},
|
|
804
|
+
toggleExportMode: function(params) {
|
|
805
|
+
const result = toggleExportMode(params);
|
|
806
|
+
window.parent.postMessage({
|
|
807
|
+
type: 'functionResult',
|
|
808
|
+
method: 'toggleExportMode',
|
|
809
|
+
result: result
|
|
810
|
+
}, '*');
|
|
811
|
+
return result;
|
|
812
|
+
},
|
|
813
|
+
openCustomError: function (params) {
|
|
814
|
+
const { nodeId, nodeType, errorMessage, borderColor='#FF0000' } = params;
|
|
815
|
+
const nodeIds = Array.isArray(nodeId) ? nodeId : [nodeId];
|
|
816
|
+
function injectErrorDialogStyles() {
|
|
817
|
+
const styleId = 'custom-error-dialog-styles';
|
|
818
|
+
if (document.getElementById(styleId)) {
|
|
819
|
+
return; // 样式已经存在
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
const style = document.createElement('style');
|
|
823
|
+
style.id = styleId;
|
|
824
|
+
style.textContent = `
|
|
825
|
+
.comfy-error-report .no-results-placeholder p {
|
|
826
|
+
text-align: left;
|
|
827
|
+
}
|
|
828
|
+
`;
|
|
829
|
+
document.head.appendChild(style);
|
|
830
|
+
};
|
|
831
|
+
injectErrorDialogStyles()
|
|
832
|
+
function simulateExecutionError(nodeId, nodeType, errorMessage, borderColor) {
|
|
833
|
+
// const originalNodeErrorStyle = node.strokeStyles?.['nodeError']
|
|
834
|
+
const node = app.graph.getNodeById(nodeId)
|
|
835
|
+
if (!node) return
|
|
836
|
+
if (!customErrorStyles.has(nodeId)) {
|
|
837
|
+
customErrorStyles.set(nodeId, {
|
|
838
|
+
originalStyle: node.strokeStyles?.['nodeError'],
|
|
839
|
+
customColor: borderColor,
|
|
840
|
+
nodeId: nodeId
|
|
841
|
+
})
|
|
842
|
+
}
|
|
843
|
+
node.strokeStyles = node.strokeStyles || {}
|
|
844
|
+
node.strokeStyles['nodeError'] = function () {
|
|
845
|
+
// if (this.id === nodeId) {
|
|
846
|
+
return { color: borderColor, lineWidth: 2 } // 自定义颜色和线宽
|
|
847
|
+
// }
|
|
848
|
+
}
|
|
849
|
+
const mockErrorEvent = {
|
|
850
|
+
detail: {
|
|
851
|
+
node_id: nodeId,
|
|
852
|
+
node_type: nodeType,
|
|
853
|
+
exception_message: errorMessage,
|
|
854
|
+
exception_type: 'ManualError',
|
|
855
|
+
traceback: ['Manual error triggered'],
|
|
856
|
+
executed: [],
|
|
857
|
+
prompt_id: 'manual',
|
|
858
|
+
timestamp: Date.now()
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// 手动触发事件监听器
|
|
863
|
+
app.api.dispatchCustomEvent('execution_error', mockErrorEvent.detail)
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
nodeIds.forEach(id => {
|
|
867
|
+
simulateExecutionError(id, nodeType, errorMessage, borderColor)
|
|
868
|
+
})
|
|
869
|
+
|
|
870
|
+
app.canvas.draw(true, true)
|
|
871
|
+
window.parent.postMessage({
|
|
872
|
+
type: 'functionResult',
|
|
873
|
+
method: 'openCustomError',
|
|
874
|
+
result: true
|
|
875
|
+
}, '*');
|
|
876
|
+
},
|
|
877
|
+
clearAllCustomStyles: function () {
|
|
878
|
+
customErrorStyles.forEach((styleInfo, nodeId) => {
|
|
879
|
+
const node = app.graph.getNodeById(nodeId)
|
|
880
|
+
if (!node) return
|
|
881
|
+
console.log(node)
|
|
882
|
+
// 恢复原始样式
|
|
883
|
+
if (styleInfo.originalStyle) {
|
|
884
|
+
node.strokeStyles['nodeError'] = styleInfo.originalStyle
|
|
885
|
+
} else {
|
|
886
|
+
delete node.strokeStyles['nodeError']
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// 从映射中移除
|
|
890
|
+
customErrorStyles.delete(nodeId)
|
|
891
|
+
})
|
|
892
|
+
|
|
893
|
+
// 重绘画布
|
|
894
|
+
app.canvas.draw(true, true)
|
|
895
|
+
},
|
|
896
|
+
focusNodeOnly: function(params) {
|
|
897
|
+
if (!params.nodeId) return false;
|
|
898
|
+
const result = focusNodeOnly(params.nodeId);
|
|
899
|
+
window.parent.postMessage({
|
|
900
|
+
type: 'functionResult',
|
|
901
|
+
method: 'focusNodeOnly',
|
|
902
|
+
result: result
|
|
903
|
+
}, '*');
|
|
904
|
+
return result;
|
|
905
|
+
},
|
|
706
906
|
};
|
|
707
907
|
|
|
908
|
+
methods.deselectExportNode = function(params) {
|
|
909
|
+
if (params && params.nodeId !== undefined) {
|
|
910
|
+
if (typeof window.deselectInputNode === 'function') {
|
|
911
|
+
window.deselectInputNode(params.nodeId);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
methods.clearExportNodes = function() {
|
|
916
|
+
if (typeof window.clearExportNodes === 'function') {
|
|
917
|
+
window.clearExportNodes();
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
// 保存工作流的原始节点颜色信息
|
|
921
|
+
methods.saveOriginalNodeColors = function(params) {
|
|
922
|
+
if (typeof window.saveOriginalNodeColors === 'function') {
|
|
923
|
+
window.saveOriginalNodeColors(params.workflowId);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
708
926
|
window.addEventListener('message', function (event) {
|
|
709
927
|
if (event.data && event.data.type === 'callMethod') {
|
|
710
928
|
const methodName = event.data.method;
|
|
@@ -732,5 +950,17 @@ app.registerExtension({
|
|
|
732
950
|
}
|
|
733
951
|
});
|
|
734
952
|
window.parent.postMessage({ type: 'iframeReady' }, '*');
|
|
953
|
+
app.api.addEventListener('graphChanged', (e) => {
|
|
954
|
+
console.log('Graph 发生变化,当前 workflow JSON:', e.detail)
|
|
955
|
+
window.parent.postMessage({
|
|
956
|
+
type: 'functionResult',
|
|
957
|
+
method: 'workflowChanged',
|
|
958
|
+
result: e.detail
|
|
959
|
+
}, '*');
|
|
960
|
+
|
|
961
|
+
document.dispatchEvent(new CustomEvent('workflowLoaded', {
|
|
962
|
+
detail: e.detail
|
|
963
|
+
}));
|
|
964
|
+
})
|
|
735
965
|
}
|
|
736
966
|
});
|
bizydraft/static/js/tool.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
const loadNodeList = [
|
|
2
|
+
'LoadImage',
|
|
3
|
+
'LoadImageMask',
|
|
4
|
+
'LoadAudio',
|
|
5
|
+
'LoadVideo',
|
|
6
|
+
'Load3D',
|
|
7
|
+
]
|
|
8
|
+
const extMap = {
|
|
9
|
+
'LoadImage': '.png,.jpg,.jpeg,.webp,.gif,.svg,.ico,.bmp,.tiff,.tif,.heic,.heif',
|
|
10
|
+
'LoadImageMask': '.png,.jpg,.jpeg,.webp,.gif,.svg,.ico,.bmp,.tiff,.tif,.heic,.heif',
|
|
11
|
+
'LoadAudio': '.mp3,.wav,.ogg,.m4a,.aac,.flac,.wma,.m4r',
|
|
12
|
+
'LoadVideo': '.mp4,.mov,.avi,.mkv,.webm,.flv,.wmv,.m4v',
|
|
13
|
+
'Load3D': '.glb,.gltf,.fbx,.obj,.dae,.ply,.stl',
|
|
14
|
+
}
|
|
1
15
|
export function getCookie(name) {
|
|
2
16
|
const value = `; ${document.cookie}`;
|
|
3
17
|
const parts = value.split(`; ${name}=`);
|
|
@@ -22,3 +36,49 @@ export const hideWidget = (node, widget_name) => {
|
|
|
22
36
|
widget.height = undefined;
|
|
23
37
|
};
|
|
24
38
|
}
|
|
39
|
+
export const computeIsLoadNode = (nodeName) => {
|
|
40
|
+
|
|
41
|
+
return loadNodeList.includes(nodeName)
|
|
42
|
+
}
|
|
43
|
+
export const computeExt = (nodeName) => {
|
|
44
|
+
|
|
45
|
+
return extMap[nodeName] || ''
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 判断节点名是否为模型加载类(不包含 bizyair)
|
|
49
|
+
* @param {string} nodeName
|
|
50
|
+
* @returns {boolean}
|
|
51
|
+
*/
|
|
52
|
+
function isModelLoaderType(nodeName) {
|
|
53
|
+
const regex = /^(\w+).*Loader.*/i;
|
|
54
|
+
return regex.test(nodeName);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 处理 graphData.output
|
|
59
|
+
* @param {Object} output - graphData.output 对象
|
|
60
|
+
* @returns {Object} 处理后的新对象
|
|
61
|
+
*/
|
|
62
|
+
export function processGraphOutput(output) {
|
|
63
|
+
const newOutput = JSON.parse(JSON.stringify(output));
|
|
64
|
+
for (const key in newOutput) {
|
|
65
|
+
const node = newOutput[key];
|
|
66
|
+
// 1. 如果 class_type 在 loadNodeList 里,删除 inputs.image_name
|
|
67
|
+
if (loadNodeList.includes(node.class_type) && node.inputs && node.inputs.image_name !== undefined) {
|
|
68
|
+
delete node.inputs.image_name;
|
|
69
|
+
}
|
|
70
|
+
if (isModelLoaderType(node.class_type)) {
|
|
71
|
+
delete newOutput[key];
|
|
72
|
+
}
|
|
73
|
+
// 2. 如果 class_type 满足 Loader 正则且不包含 bizyair,删除 inputs.model_version_id
|
|
74
|
+
if (isModelLoaderType(node.class_type) && node.inputs) {
|
|
75
|
+
if (node.inputs.model_version_id !== undefined) {
|
|
76
|
+
delete node.inputs.model_version_id;
|
|
77
|
+
}
|
|
78
|
+
if (node.inputs.ckpt_name !== undefined) {
|
|
79
|
+
delete node.inputs.ckpt_name;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return newOutput;
|
|
84
|
+
}
|
bizydraft/workflow_io.py
CHANGED
|
@@ -83,10 +83,10 @@ def summarize_params(
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def get_node_id_from_wf_nodes(
|
|
86
|
-
wf_nodes: List[Dict[str, Any]], node_id:
|
|
86
|
+
wf_nodes: List[Dict[str, Any]], node_id: str
|
|
87
87
|
) -> Dict[str, Any]:
|
|
88
88
|
for wf_node in wf_nodes:
|
|
89
|
-
if wf_node.get("id", 0) == node_id:
|
|
89
|
+
if str(wf_node.get("id", 0)) == node_id:
|
|
90
90
|
return wf_node
|
|
91
91
|
return None
|
|
92
92
|
|