bizydraft 0.1.30__py3-none-any.whl → 0.2.0__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.

@@ -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
+ };
@@ -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
- const changeSocketUrl = this.changeSocketUrl.bind(this);
418
- const sendSocketMessage = this.sendSocketMessage.bind(this);
419
- const sendPrompt = this.sendPrompt.bind(this);
420
- const startPing = this.startPing.bind(this);
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
- await app.queuePrompt(graph.output);
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
  });
@@ -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: int
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
 
@@ -1,4 +1,4 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bizydraft
3
- Version: 0.1.30
3
+ Version: 0.2.0
4
4
  Summary: bizydraft