comfyui-frontend-package 1.37.3__py3-none-any.whl → 1.37.4__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.
Files changed (127) hide show
  1. comfyui_frontend_package/static/assets/AboutPanel-BwfERTOT.js +2 -0
  2. comfyui_frontend_package/static/assets/{AboutPanel-6wNn9DuA.js.map → AboutPanel-BwfERTOT.js.map} +1 -1
  3. comfyui_frontend_package/static/assets/{AudioPreviewPlayer-ybC6cXRM.js → AudioPreviewPlayer-DT9nrYD6.js} +2 -2
  4. comfyui_frontend_package/static/assets/{AudioPreviewPlayer-ybC6cXRM.js.map → AudioPreviewPlayer-DT9nrYD6.js.map} +1 -1
  5. comfyui_frontend_package/static/assets/ComfyQueueButton-DazIfwpa.js +2 -0
  6. comfyui_frontend_package/static/assets/{ComfyQueueButton-BbIk3ALi.js.map → ComfyQueueButton-DazIfwpa.js.map} +1 -1
  7. comfyui_frontend_package/static/assets/ExtensionPanel-D539Wx81.js +2 -0
  8. comfyui_frontend_package/static/assets/{ExtensionPanel-DYw7d35v.js.map → ExtensionPanel-D539Wx81.js.map} +1 -1
  9. comfyui_frontend_package/static/assets/GraphView-C_FQc1Au.js +16 -0
  10. comfyui_frontend_package/static/assets/GraphView-C_FQc1Au.js.map +1 -0
  11. comfyui_frontend_package/static/assets/{GraphView-DwAYVX4H.css → GraphView-Ck9hVEEV.css} +1 -1
  12. comfyui_frontend_package/static/assets/{KeybindingPanel-D0MD69FX.js → KeybindingPanel-Bj61UMoX.js} +2 -2
  13. comfyui_frontend_package/static/assets/{KeybindingPanel-D0MD69FX.js.map → KeybindingPanel-Bj61UMoX.js.map} +1 -1
  14. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js +2 -0
  15. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js.map +1 -0
  16. comfyui_frontend_package/static/assets/LegacyCreditsPanel-BNqPlgUn.js +2 -0
  17. comfyui_frontend_package/static/assets/{LegacyCreditsPanel-BMvul305.js.map → LegacyCreditsPanel-BNqPlgUn.js.map} +1 -1
  18. comfyui_frontend_package/static/assets/Load3D-CaNKqgIL.js +2 -0
  19. comfyui_frontend_package/static/assets/Load3D-CaNKqgIL.js.map +1 -0
  20. comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BtNou66j.js → Load3D.vue_vue_type_script_setup_true_lang-gf2aN2_8.js} +2 -2
  21. comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BtNou66j.js.map → Load3D.vue_vue_type_script_setup_true_lang-gf2aN2_8.js.map} +1 -1
  22. comfyui_frontend_package/static/assets/{Media3DBottom-Bk7TM-zH.js → Media3DBottom-D9M9b2ls.js} +2 -2
  23. comfyui_frontend_package/static/assets/{Media3DBottom-Bk7TM-zH.js.map → Media3DBottom-D9M9b2ls.js.map} +1 -1
  24. comfyui_frontend_package/static/assets/{Media3DTop-CIsQ4Ccc.js → Media3DTop-B-qNqlQF.js} +2 -2
  25. comfyui_frontend_package/static/assets/{Media3DTop-CIsQ4Ccc.js.map → Media3DTop-B-qNqlQF.js.map} +1 -1
  26. comfyui_frontend_package/static/assets/{MediaAudioBottom-CWxtJ5vP.js → MediaAudioBottom-d7EZ2Wx5.js} +2 -2
  27. comfyui_frontend_package/static/assets/{MediaAudioBottom-CWxtJ5vP.js.map → MediaAudioBottom-d7EZ2Wx5.js.map} +1 -1
  28. comfyui_frontend_package/static/assets/{MediaImageBottom-OWiMf_6W.js → MediaImageBottom-B-9SOOhn.js} +2 -2
  29. comfyui_frontend_package/static/assets/{MediaImageBottom-OWiMf_6W.js.map → MediaImageBottom-B-9SOOhn.js.map} +1 -1
  30. comfyui_frontend_package/static/assets/{MediaTitle.vue_vue_type_script_setup_true_lang-C59zAxW0.js → MediaTitle.vue_vue_type_script_setup_true_lang-DVzYM9UW.js} +2 -2
  31. comfyui_frontend_package/static/assets/{MediaTitle.vue_vue_type_script_setup_true_lang-C59zAxW0.js.map → MediaTitle.vue_vue_type_script_setup_true_lang-DVzYM9UW.js.map} +1 -1
  32. comfyui_frontend_package/static/assets/{MediaVideoBottom-OKuLWTbn.js → MediaVideoBottom-D6IR52ja.js} +2 -2
  33. comfyui_frontend_package/static/assets/{MediaVideoBottom-OKuLWTbn.js.map → MediaVideoBottom-D6IR52ja.js.map} +1 -1
  34. comfyui_frontend_package/static/assets/{ServerConfigPanel-5RPRkuvl.js → ServerConfigPanel-BBWOQ7ej.js} +2 -2
  35. comfyui_frontend_package/static/assets/{ServerConfigPanel-5RPRkuvl.js.map → ServerConfigPanel-BBWOQ7ej.js.map} +1 -1
  36. comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-CtCWM_jj.js → SubscriptionRequiredDialogContent-oUSDZGJZ.js} +2 -2
  37. comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-CtCWM_jj.js.map → SubscriptionRequiredDialogContent-oUSDZGJZ.js.map} +1 -1
  38. comfyui_frontend_package/static/assets/{UserPanel-CrxHTRQZ.js → UserPanel-Do_alb49.js} +2 -2
  39. comfyui_frontend_package/static/assets/{UserPanel-CrxHTRQZ.js.map → UserPanel-Do_alb49.js.map} +1 -1
  40. comfyui_frontend_package/static/assets/{UserSelectView-tu0lXAri.js → UserSelectView-DVJzD33o.js} +2 -2
  41. comfyui_frontend_package/static/assets/{UserSelectView-tu0lXAri.js.map → UserSelectView-DVJzD33o.js.map} +1 -1
  42. comfyui_frontend_package/static/assets/{ValueControlPopover-CgyNfIEw.js → ValueControlPopover-CZIsPw9J.js} +2 -2
  43. comfyui_frontend_package/static/assets/{ValueControlPopover-CgyNfIEw.js.map → ValueControlPopover-CZIsPw9J.js.map} +1 -1
  44. comfyui_frontend_package/static/assets/WidgetAudioUI-CbC597q0.js +2 -0
  45. comfyui_frontend_package/static/assets/{WidgetAudioUI-BZL35TlT.js.map → WidgetAudioUI-CbC597q0.js.map} +1 -1
  46. comfyui_frontend_package/static/assets/{WidgetButton-Dkge0J8R.js → WidgetButton-Df2ihQh6.js} +2 -2
  47. comfyui_frontend_package/static/assets/{WidgetButton-Dkge0J8R.js.map → WidgetButton-Df2ihQh6.js.map} +1 -1
  48. comfyui_frontend_package/static/assets/{WidgetColorPicker-vRHta_Kz.js → WidgetColorPicker-DgI8RjHJ.js} +2 -2
  49. comfyui_frontend_package/static/assets/{WidgetColorPicker-vRHta_Kz.js.map → WidgetColorPicker-DgI8RjHJ.js.map} +1 -1
  50. comfyui_frontend_package/static/assets/{WidgetGalleria-BoWBT6i_.js → WidgetGalleria-Cyz9lzP-.js} +2 -2
  51. comfyui_frontend_package/static/assets/{WidgetGalleria-BoWBT6i_.js.map → WidgetGalleria-Cyz9lzP-.js.map} +1 -1
  52. comfyui_frontend_package/static/assets/WidgetInputNumber-wD2uHC32.js +2 -0
  53. comfyui_frontend_package/static/assets/WidgetInputNumber-wD2uHC32.js.map +1 -0
  54. comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-aeh2Ot2n.js → WidgetInputNumber.vue_vue_type_script_setup_true_lang-XbRdxGIz.js} +2 -2
  55. comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-aeh2Ot2n.js.map → WidgetInputNumber.vue_vue_type_script_setup_true_lang-XbRdxGIz.js.map} +1 -1
  56. comfyui_frontend_package/static/assets/{WidgetInputText-BRV8PzCv.js → WidgetInputText-BR3C0fCV.js} +2 -2
  57. comfyui_frontend_package/static/assets/{WidgetInputText-BRV8PzCv.js.map → WidgetInputText-BR3C0fCV.js.map} +1 -1
  58. comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-Dps42A-g.js → WidgetLayoutField.vue_vue_type_script_setup_true_lang-CZj3E4v6.js} +2 -2
  59. comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-Dps42A-g.js.map → WidgetLayoutField.vue_vue_type_script_setup_true_lang-CZj3E4v6.js.map} +1 -1
  60. comfyui_frontend_package/static/assets/WidgetLegacy-CkV176Xm.js +2 -0
  61. comfyui_frontend_package/static/assets/WidgetLegacy-CkV176Xm.js.map +1 -0
  62. comfyui_frontend_package/static/assets/WidgetMarkdown-rM_UPCA-.js +2 -0
  63. comfyui_frontend_package/static/assets/{WidgetMarkdown-DIMd79hN.js.map → WidgetMarkdown-rM_UPCA-.js.map} +1 -1
  64. comfyui_frontend_package/static/assets/{WidgetRecordAudio-DwHSqiBz.js → WidgetRecordAudio-CLpvV8e9.js} +2 -2
  65. comfyui_frontend_package/static/assets/{WidgetRecordAudio-DwHSqiBz.js.map → WidgetRecordAudio-CLpvV8e9.js.map} +1 -1
  66. comfyui_frontend_package/static/assets/WidgetSelect-BwcPw-lE.js +2 -0
  67. comfyui_frontend_package/static/assets/WidgetSelect-BwcPw-lE.js.map +1 -0
  68. comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-CMg0GtSC.js → WidgetSelect.vue_vue_type_script_setup_true_lang-CITubFAk.js} +2 -2
  69. comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-CMg0GtSC.js.map → WidgetSelect.vue_vue_type_script_setup_true_lang-CITubFAk.js.map} +1 -1
  70. comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js → WidgetTextarea-CwUMJ-23.js} +2 -2
  71. comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js.map → WidgetTextarea-CwUMJ-23.js.map} +1 -1
  72. comfyui_frontend_package/static/assets/{WidgetToggleSwitch-DwYqmS17.js → WidgetToggleSwitch-DqQpfrDq.js} +2 -2
  73. comfyui_frontend_package/static/assets/{WidgetToggleSwitch-DwYqmS17.js.map → WidgetToggleSwitch-DqQpfrDq.js.map} +1 -1
  74. comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-COy_p9Eh.js → WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js} +3 -3
  75. comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-COy_p9Eh.js.map → WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js.map} +1 -1
  76. comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js → audioService-DKN4T_Yr.js} +2 -2
  77. comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js.map → audioService-DKN4T_Yr.js.map} +1 -1
  78. comfyui_frontend_package/static/assets/{audioUtils-DlA-QHPJ.js → audioUtils-WBbpBG9r.js} +2 -2
  79. comfyui_frontend_package/static/assets/{audioUtils-DlA-QHPJ.js.map → audioUtils-WBbpBG9r.js.map} +1 -1
  80. comfyui_frontend_package/static/assets/{commands-CHktpNSL.js → commands-CRVPkENB.js} +2 -2
  81. comfyui_frontend_package/static/assets/commands-CRVPkENB.js.map +1 -0
  82. comfyui_frontend_package/static/assets/{index-2-qFLlQP.js → index-CuKlxAeN.js} +30 -28
  83. comfyui_frontend_package/static/assets/index-CuKlxAeN.js.map +1 -0
  84. comfyui_frontend_package/static/assets/index-Cv1aHIoL.css +1 -0
  85. comfyui_frontend_package/static/assets/{index-_AAd9eTu.js → index-DEqR9lwu.js} +2 -2
  86. comfyui_frontend_package/static/assets/{index-_AAd9eTu.js.map → index-DEqR9lwu.js.map} +1 -1
  87. comfyui_frontend_package/static/assets/index-KizWjI6s.js +5 -0
  88. comfyui_frontend_package/static/assets/{index-DKofvZ3r.js.map → index-KizWjI6s.js.map} +1 -1
  89. comfyui_frontend_package/static/assets/{keybindingService-CWbdWLPI.js → keybindingService-O5KDQleT.js} +2 -2
  90. comfyui_frontend_package/static/assets/{keybindingService-CWbdWLPI.js.map → keybindingService-O5KDQleT.js.map} +1 -1
  91. comfyui_frontend_package/static/assets/main-10VBfKWj.js +14 -0
  92. comfyui_frontend_package/static/assets/main-10VBfKWj.js.map +1 -0
  93. comfyui_frontend_package/static/assets/nodeDefs-D9VHUZJt.js +53 -0
  94. comfyui_frontend_package/static/assets/nodeDefs-D9VHUZJt.js.map +1 -0
  95. comfyui_frontend_package/static/assets/{vendor-three-BKWXAgVe.js → vendor-three-29bN5sfh.js} +2 -2
  96. comfyui_frontend_package/static/assets/{vendor-three-BKWXAgVe.js.map → vendor-three-29bN5sfh.js.map} +1 -1
  97. comfyui_frontend_package/static/index.html +1 -1
  98. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/METADATA +1 -1
  99. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/RECORD +101 -101
  100. comfyui_frontend_package/static/assets/AboutPanel-6wNn9DuA.js +0 -2
  101. comfyui_frontend_package/static/assets/ComfyQueueButton-BbIk3ALi.js +0 -2
  102. comfyui_frontend_package/static/assets/ExtensionPanel-DYw7d35v.js +0 -2
  103. comfyui_frontend_package/static/assets/GraphView-CjDjhvN7.js +0 -16
  104. comfyui_frontend_package/static/assets/GraphView-CjDjhvN7.js.map +0 -1
  105. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js +0 -2
  106. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js.map +0 -1
  107. comfyui_frontend_package/static/assets/LegacyCreditsPanel-BMvul305.js +0 -2
  108. comfyui_frontend_package/static/assets/Load3D-BplYUML3.js +0 -2
  109. comfyui_frontend_package/static/assets/Load3D-BplYUML3.js.map +0 -1
  110. comfyui_frontend_package/static/assets/WidgetAudioUI-BZL35TlT.js +0 -2
  111. comfyui_frontend_package/static/assets/WidgetInputNumber-DMqIMaoH.js +0 -2
  112. comfyui_frontend_package/static/assets/WidgetInputNumber-DMqIMaoH.js.map +0 -1
  113. comfyui_frontend_package/static/assets/WidgetLegacy-BWDBwsli.js +0 -2
  114. comfyui_frontend_package/static/assets/WidgetLegacy-BWDBwsli.js.map +0 -1
  115. comfyui_frontend_package/static/assets/WidgetMarkdown-DIMd79hN.js +0 -2
  116. comfyui_frontend_package/static/assets/WidgetSelect-BOvzWMtV.js +0 -2
  117. comfyui_frontend_package/static/assets/WidgetSelect-BOvzWMtV.js.map +0 -1
  118. comfyui_frontend_package/static/assets/commands-CHktpNSL.js.map +0 -1
  119. comfyui_frontend_package/static/assets/index-2-qFLlQP.js.map +0 -1
  120. comfyui_frontend_package/static/assets/index-571Fkv7y.css +0 -1
  121. comfyui_frontend_package/static/assets/index-DKofvZ3r.js +0 -5
  122. comfyui_frontend_package/static/assets/main-DGOENlHZ.js +0 -14
  123. comfyui_frontend_package/static/assets/main-DGOENlHZ.js.map +0 -1
  124. comfyui_frontend_package/static/assets/nodeDefs-DtmuHPr3.js +0 -53
  125. comfyui_frontend_package/static/assets/nodeDefs-DtmuHPr3.js.map +0 -1
  126. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/WHEEL +0 -0
  127. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index-DKofvZ3r.js","sources":["../../src/extensions/core/clipspace.ts","../../src/extensions/core/contextMenuFilter.ts","../../src/extensions/core/customCombo.ts","../../src/extensions/core/dynamicPrompts.ts","../../src/extensions/core/editAttention.ts","../../src/constants/uvMirrors.ts","../../src/utils/electronMirrorCheck.ts","../../src/extensions/core/electronAdapter.ts","../../src/utils/executableGroupNodeChildDTO.ts","../../src/extensions/core/groupNodeManage.ts","../../src/utils/nodeDefUtil.ts","../../src/renderer/utils/nodeTypeGuards.ts","../../src/extensions/core/widgetInputs.ts","../../src/extensions/core/groupNode.ts","../../src/extensions/core/groupOptions.ts","../../src/extensions/core/imageCompare.ts","../../src/extensions/core/load3d/exportMenuHelper.ts","../../src/extensions/core/load3d/Load3DConfiguration.ts","../../src/extensions/core/load3d.ts","../../src/extensions/core/maskeditor.ts","../../src/extensions/core/nodeTemplates.ts","../../src/extensions/core/noteNode.ts","../../src/extensions/core/previewAny.ts","../../src/extensions/core/rerouteNode.ts","../../src/extensions/core/saveImageExtraOutput.ts","../../src/extensions/core/saveMesh.ts","../../src/extensions/core/selectionBorder.ts","../../src/extensions/core/simpleTouchSupport.ts","../../src/extensions/core/slotDefaults.ts","../../src/extensions/core/uploadAudio.ts","../../src/extensions/core/uploadImage.ts","../../src/extensions/core/webcamCapture.ts"],"sourcesContent":["import { app } from '../../scripts/app'\nimport { ComfyApp } from '../../scripts/app'\nimport { $el, ComfyDialog } from '../../scripts/ui'\n\nexport class ClipspaceDialog extends ComfyDialog {\n static items: Array<\n HTMLButtonElement & {\n contextPredicate?: () => boolean\n }\n > = []\n static instance: ClipspaceDialog | null = null\n\n static registerButton(\n name: string,\n contextPredicate: () => boolean,\n callback: () => void\n ) {\n const item = $el('button', {\n type: 'button',\n textContent: name,\n contextPredicate: contextPredicate,\n onclick: callback\n })\n\n ClipspaceDialog.items.push(item)\n }\n\n static invalidatePreview() {\n if (\n ComfyApp.clipspace &&\n ComfyApp.clipspace.imgs &&\n ComfyApp.clipspace.imgs.length > 0\n ) {\n const img_preview = document.getElementById(\n 'clipspace_preview'\n ) as HTMLImageElement\n if (img_preview) {\n img_preview.src =\n ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src\n img_preview.style.maxHeight = '100%'\n img_preview.style.maxWidth = '100%'\n }\n }\n }\n\n static invalidate() {\n if (ClipspaceDialog.instance) {\n const self = ClipspaceDialog.instance\n // allow reconstruct controls when copying from non-image to image content.\n const children = $el('div.comfy-modal-content', [\n self.createImgSettings(),\n ...self.createButtons()\n ])\n\n if (self.element) {\n // update\n if (self.element.firstChild) {\n self.element.removeChild(self.element.firstChild)\n }\n self.element.appendChild(children)\n } else {\n // new\n self.element = $el('div.comfy-modal', { parent: document.body }, [\n children\n ])\n }\n\n if (self.element.children[0].children.length <= 1) {\n self.element.children[0].appendChild(\n $el('p', {}, [\n 'Unable to find the features to edit content of a format stored in the current Clipspace.'\n ])\n )\n }\n\n ClipspaceDialog.invalidatePreview()\n }\n }\n\n constructor() {\n super()\n }\n\n override createButtons() {\n const buttons = []\n\n for (let idx in ClipspaceDialog.items) {\n const item = ClipspaceDialog.items[idx]\n if (!item.contextPredicate || item.contextPredicate())\n buttons.push(ClipspaceDialog.items[idx])\n }\n\n buttons.push(\n $el('button', {\n type: 'button',\n textContent: 'Close',\n onclick: () => {\n this.close()\n }\n })\n )\n\n return buttons\n }\n\n createImgSettings() {\n if (ComfyApp.clipspace?.imgs) {\n const combo_items = []\n const imgs = ComfyApp.clipspace.imgs\n\n for (let i = 0; i < imgs.length; i++) {\n combo_items.push($el('option', { value: i }, [`${i}`]))\n }\n\n const combo1 = $el(\n 'select',\n {\n id: 'clipspace_img_selector',\n onchange: (event: Event) => {\n if (event.target && ComfyApp.clipspace) {\n ComfyApp.clipspace['selectedIndex'] = (\n event.target as HTMLSelectElement\n ).selectedIndex\n ClipspaceDialog.invalidatePreview()\n }\n }\n },\n combo_items\n )\n\n const row1 = $el('tr', {}, [\n $el('td', {}, [$el('font', { color: 'white' }, ['Select Image'])]),\n $el('td', {}, [combo1])\n ])\n\n const combo2 = $el(\n 'select',\n {\n id: 'clipspace_img_paste_mode',\n onchange: (event: Event) => {\n if (event.target && ComfyApp.clipspace) {\n ComfyApp.clipspace['img_paste_mode'] = (\n event.target as HTMLSelectElement\n ).value\n }\n }\n },\n [\n $el('option', { value: 'selected' }, 'selected'),\n $el('option', { value: 'all' }, 'all')\n ]\n ) as HTMLSelectElement\n combo2.value = ComfyApp.clipspace['img_paste_mode']\n\n const row2 = $el('tr', {}, [\n $el('td', {}, [$el('font', { color: 'white' }, ['Paste Mode'])]),\n $el('td', {}, [combo2])\n ])\n\n const td = $el(\n 'td',\n { align: 'center', width: '100px', height: '100px', colSpan: '2' },\n [$el('img', { id: 'clipspace_preview', ondragstart: () => false }, [])]\n )\n\n const row3 = $el('tr', {}, [td])\n\n return $el('table', {}, [row1, row2, row3])\n } else {\n return []\n }\n }\n\n createImgPreview() {\n if (ComfyApp.clipspace?.imgs) {\n return $el('img', { id: 'clipspace_preview', ondragstart: () => false })\n } else return []\n }\n\n override show() {\n ClipspaceDialog.invalidate()\n\n this.element.style.display = 'block'\n }\n}\n\napp.registerExtension({\n name: 'Comfy.Clipspace',\n init(app) {\n app.openClipspace = function () {\n if (!ClipspaceDialog.instance) {\n ClipspaceDialog.instance = new ClipspaceDialog()\n ComfyApp.clipspace_invalidate_handler = ClipspaceDialog.invalidate\n }\n\n if (ComfyApp.clipspace) {\n ClipspaceDialog.instance.show()\n } else app.ui.dialog.show('Clipspace is Empty!')\n }\n }\n})\n","import {\n LGraphCanvas,\n LiteGraph,\n isComboWidget\n} from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '../../scripts/app'\n\n// Adds filtering to combo context menus\n\nconst ext = {\n name: 'Comfy.ContextMenuFilter',\n init() {\n const ctxMenu = LiteGraph.ContextMenu\n\n // @ts-expect-error TODO Very hacky way to modify Litegraph behaviour. Fix ctx later.\n LiteGraph.ContextMenu = function (values, options) {\n const ctx = new ctxMenu(values, options)\n\n // If we are a dark menu (only used for combo boxes) then add a filter input\n if (options?.className === 'dark' && values?.length > 4) {\n const filter = document.createElement('input')\n filter.classList.add('comfy-context-menu-filter')\n filter.placeholder = 'Filter list'\n\n ctx.root.prepend(filter)\n\n const items = Array.from(\n ctx.root.querySelectorAll('.litemenu-entry')\n ) as HTMLElement[]\n let displayedItems = [...items]\n let itemCount = displayedItems.length\n\n // We must request an animation frame for the current node of the active canvas to update.\n requestAnimationFrame(() => {\n const currentNode = LGraphCanvas.active_canvas.current_node\n const clickedComboValue = currentNode?.widgets\n ?.filter(\n (w) =>\n isComboWidget(w) && w.options.values?.length === values.length\n )\n .find((w) =>\n // @ts-expect-error Poorly typed; filter above \"should\" mitigate exceptions\n w.options.values?.every((v, i) => v === values[i])\n )?.value\n\n let selectedIndex = clickedComboValue\n ? values.findIndex((v: string) => v === clickedComboValue)\n : 0\n if (selectedIndex < 0) {\n selectedIndex = 0\n }\n let selectedItem = displayedItems[selectedIndex]\n updateSelected()\n\n // Apply highlighting to the selected item\n function updateSelected() {\n selectedItem?.style.setProperty('background-color', '')\n selectedItem?.style.setProperty('color', '')\n selectedItem = displayedItems[selectedIndex]\n selectedItem?.style.setProperty(\n 'background-color',\n '#ccc',\n 'important'\n )\n selectedItem?.style.setProperty('color', '#000', 'important')\n }\n\n const positionList = () => {\n const rect = ctx.root.getBoundingClientRect()\n\n // If the top is off-screen then shift the element with scaling applied\n if (rect.top < 0) {\n const scale =\n 1 -\n ctx.root.getBoundingClientRect().height / ctx.root.clientHeight\n\n const shift = (ctx.root.clientHeight * scale) / 2\n\n ctx.root.style.top = -shift + 'px'\n }\n }\n\n // Arrow up/down to select items\n filter.addEventListener('keydown', (event) => {\n switch (event.key) {\n case 'ArrowUp':\n event.preventDefault()\n if (selectedIndex === 0) {\n selectedIndex = itemCount - 1\n } else {\n selectedIndex--\n }\n updateSelected()\n break\n case 'ArrowRight':\n event.preventDefault()\n selectedIndex = itemCount - 1\n updateSelected()\n break\n case 'ArrowDown':\n event.preventDefault()\n if (selectedIndex === itemCount - 1) {\n selectedIndex = 0\n } else {\n selectedIndex++\n }\n updateSelected()\n break\n case 'ArrowLeft':\n event.preventDefault()\n selectedIndex = 0\n updateSelected()\n break\n case 'Enter':\n selectedItem?.click()\n break\n case 'Escape':\n ctx.close()\n break\n }\n })\n\n filter.addEventListener('input', () => {\n // Hide all items that don't match our filter\n const term = filter.value.toLocaleLowerCase()\n // When filtering, recompute which items are visible for arrow up/down and maintain selection.\n displayedItems = items.filter((item) => {\n const isVisible =\n !term || item.textContent?.toLocaleLowerCase().includes(term)\n item.style.display = isVisible ? 'block' : 'none'\n return isVisible\n })\n\n selectedIndex = 0\n if (displayedItems.includes(selectedItem)) {\n selectedIndex = displayedItems.findIndex(\n (d) => d === selectedItem\n )\n }\n itemCount = displayedItems.length\n\n updateSelected()\n\n // If we have an event then we can try and position the list under the source\n if (options.event) {\n let top = options.event.clientY - 10\n\n const bodyRect = document.body.getBoundingClientRect()\n\n const rootRect = ctx.root.getBoundingClientRect()\n if (\n bodyRect.height &&\n top > bodyRect.height - rootRect.height - 10\n ) {\n top = Math.max(0, bodyRect.height - rootRect.height - 10)\n }\n\n ctx.root.style.top = top + 'px'\n positionList()\n }\n })\n\n requestAnimationFrame(() => {\n // Focus the filter box when opening\n filter.focus()\n\n positionList()\n })\n })\n }\n\n return ctx\n }\n\n LiteGraph.ContextMenu.prototype = ctxMenu.prototype\n }\n}\n\napp.registerExtension(ext)\n","import { shallowReactive } from 'vue'\n\nimport { useChainCallback } from '@/composables/functional/useChainCallback'\nimport type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'\nimport { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport { LLink } from '@/lib/litegraph/src/litegraph'\nimport { app } from '@/scripts/app'\n\nfunction applyToGraph(this: LGraphNode, extraLinks: LLink[] = []) {\n if (!this.outputs[0].links?.length || !this.graph) return\n\n const links = [\n ...this.outputs[0].links.map((l) => this.graph!.links[l]),\n ...extraLinks\n ]\n let v = this.widgets?.[0].value\n // For each output link copy our value over the original widget value\n for (const linkInfo of links) {\n const node = this.graph?.getNodeById(linkInfo.target_id)\n const input = node?.inputs[linkInfo.target_slot]\n if (!input) {\n console.warn('Unable to resolve node or input for link', linkInfo)\n continue\n }\n\n const widgetName = input.widget?.name\n if (!widgetName) {\n console.warn('Invalid widget or widget name', input.widget)\n continue\n }\n\n const widget = node.widgets?.find((w) => w.name === widgetName)\n if (!widget) {\n console.warn(`Unable to find widget \"${widgetName}\" on node [${node.id}]`)\n continue\n }\n\n widget.value = v\n widget.callback?.(\n widget.value,\n app.canvas,\n node,\n app.canvas.graph_mouse,\n {} as CanvasPointerEvent\n )\n }\n}\n\nfunction onNodeCreated(this: LGraphNode) {\n this.applyToGraph = useChainCallback(this.applyToGraph, applyToGraph)\n\n const comboWidget = this.widgets![0]\n const values = shallowReactive<string[]>([])\n comboWidget.options.values = values\n\n const updateCombo = () => {\n values.splice(\n 0,\n values.length,\n ...this.widgets!.filter(\n (w) => w.name.startsWith('option') && w.value\n ).map((w) => `${w.value}`)\n )\n if (app.configuringGraph) return\n if (values.includes(`${comboWidget.value}`)) return\n comboWidget.value = values[0] ?? ''\n comboWidget.callback?.(comboWidget.value)\n }\n comboWidget.callback = useChainCallback(comboWidget.callback, () =>\n this.applyToGraph!()\n )\n\n function addOption(node: LGraphNode) {\n if (!node.widgets) return\n const newCount = node.widgets.length - 1\n node.addWidget('string', `option${newCount}`, '', () => {})\n const widget = node.widgets.at(-1)\n if (!widget) return\n\n let value = ''\n Object.defineProperty(widget, 'value', {\n get() {\n return value\n },\n set(v) {\n value = v\n updateCombo()\n if (!node.widgets) return\n const lastWidget = node.widgets.at(-1)\n if (lastWidget === this) {\n if (v) addOption(node)\n return\n }\n if (v || node.widgets.at(-2) !== this || lastWidget?.value) return\n node.widgets.pop()\n node.computeSize(node.size)\n this.callback(v)\n }\n })\n }\n addOption(this)\n}\n\napp.registerExtension({\n name: 'Comfy.CustomCombo',\n beforeRegisterNodeDef(nodeType, nodeData) {\n if (nodeData?.name !== 'CustomCombo') return\n nodeType.prototype.onNodeCreated = useChainCallback(\n nodeType.prototype.onNodeCreated,\n onNodeCreated\n )\n }\n})\n","import { useExtensionService } from '@/services/extensionService'\nimport { processDynamicPrompt } from '@/utils/formatUtil'\n\n// Allows for simple dynamic prompt replacement\n// Inputs in the format {a|b} will have a random value of a or b chosen when the prompt is queued.\n\nuseExtensionService().registerExtension({\n name: 'Comfy.DynamicPrompts',\n nodeCreated(node) {\n if (node.widgets) {\n // Locate dynamic prompt text widgets\n // Include any widgets with dynamicPrompts set to true, and customtext\n const widgets = node.widgets.filter((w) => w.dynamicPrompts)\n for (const widget of widgets) {\n // Override the serialization of the value to resolve dynamic prompts for all widgets supporting it in this node\n widget.serializeValue = (workflowNode, widgetIndex) => {\n if (typeof widget.value !== 'string') return widget.value\n\n const prompt = processDynamicPrompt(widget.value)\n\n // Overwrite the value in the serialized workflow pnginfo\n if (workflowNode?.widgets_values)\n workflowNode.widgets_values[widgetIndex] = prompt\n\n return prompt\n }\n }\n }\n }\n})\n","import { app } from '../../scripts/app'\n\n// Allows you to edit the attention weight by holding ctrl (or cmd) and using the up/down arrow keys\n\napp.registerExtension({\n name: 'Comfy.EditAttention',\n init() {\n const editAttentionDelta = app.ui.settings.addSetting({\n id: 'Comfy.EditAttention.Delta',\n category: ['Comfy', 'EditTokenWeight', 'Delta'],\n name: 'Ctrl+up/down precision',\n type: 'slider',\n attrs: {\n min: 0.01,\n max: 0.5,\n step: 0.01\n },\n defaultValue: 0.05\n })\n\n function incrementWeight(weight: string, delta: number): string {\n const floatWeight = parseFloat(weight)\n if (isNaN(floatWeight)) return weight\n const newWeight = floatWeight + delta\n return String(Number(newWeight.toFixed(10)))\n }\n\n type Enclosure = {\n start: number\n end: number\n }\n\n function findNearestEnclosure(\n text: string,\n cursorPos: number\n ): Enclosure | null {\n let start = cursorPos,\n end = cursorPos\n let openCount = 0,\n closeCount = 0\n\n // Find opening parenthesis before cursor\n while (start >= 0) {\n start--\n if (text[start] === '(' && openCount === closeCount) break\n if (text[start] === '(') openCount++\n if (text[start] === ')') closeCount++\n }\n if (start < 0) return null\n\n openCount = 0\n closeCount = 0\n\n // Find closing parenthesis after cursor\n while (end < text.length) {\n if (text[end] === ')' && openCount === closeCount) break\n if (text[end] === '(') openCount++\n if (text[end] === ')') closeCount++\n end++\n }\n if (end === text.length) return null\n\n return { start: start + 1, end: end }\n }\n\n function addWeightToParentheses(text: string): string {\n const parenRegex = /^\\((.*)\\)$/\n const parenMatch = text.match(parenRegex)\n\n const floatRegex = /:([+-]?(\\d*\\.)?\\d+([eE][+-]?\\d+)?)/\n const floatMatch = text.match(floatRegex)\n\n if (parenMatch && !floatMatch) {\n return `(${parenMatch[1]}:1.0)`\n } else {\n return text\n }\n }\n\n function editAttention(event: KeyboardEvent) {\n // @ts-expect-error Runtime narrowing not impl.\n const inputField: HTMLTextAreaElement = event.composedPath()[0]\n const delta = parseFloat(editAttentionDelta.value)\n\n if (inputField.tagName !== 'TEXTAREA') return\n if (!(event.key === 'ArrowUp' || event.key === 'ArrowDown')) return\n if (!event.ctrlKey && !event.metaKey) return\n\n event.preventDefault()\n\n let start = inputField.selectionStart\n let end = inputField.selectionEnd\n let selectedText = inputField.value.substring(start, end)\n\n // If there is no selection, attempt to find the nearest enclosure, or select the current word\n if (!selectedText) {\n const nearestEnclosure = findNearestEnclosure(inputField.value, start)\n if (nearestEnclosure) {\n start = nearestEnclosure.start\n end = nearestEnclosure.end\n selectedText = inputField.value.substring(start, end)\n } else {\n // Select the current word, find the start and end of the word\n const delimiters = ' .,\\\\/!?%^*;:{}=-_`~()\\r\\n\\t'\n\n while (\n !delimiters.includes(inputField.value[start - 1]) &&\n start > 0\n ) {\n start--\n }\n\n while (\n !delimiters.includes(inputField.value[end]) &&\n end < inputField.value.length\n ) {\n end++\n }\n\n selectedText = inputField.value.substring(start, end)\n if (!selectedText) return\n }\n }\n\n // If the selection ends with a space, remove it\n if (selectedText[selectedText.length - 1] === ' ') {\n selectedText = selectedText.substring(0, selectedText.length - 1)\n end -= 1\n }\n\n // If there are parentheses left and right of the selection, select them\n if (\n inputField.value[start - 1] === '(' &&\n inputField.value[end] === ')'\n ) {\n start -= 1\n end += 1\n selectedText = inputField.value.substring(start, end)\n }\n\n // If the selection is not enclosed in parentheses, add them\n if (\n selectedText[0] !== '(' ||\n selectedText[selectedText.length - 1] !== ')'\n ) {\n selectedText = `(${selectedText})`\n }\n\n // If the selection does not have a weight, add a weight of 1.0\n selectedText = addWeightToParentheses(selectedText)\n\n // Increment the weight\n const weightDelta = event.key === 'ArrowUp' ? delta : -delta\n const updatedText = selectedText.replace(\n /\\((.*):([+-]?\\d+(?:\\.\\d+)?)\\)/,\n (_, text, weight) => {\n weight = incrementWeight(weight, weightDelta)\n if (weight == 1) {\n return text\n } else {\n return `(${text}:${weight})`\n }\n }\n )\n\n inputField.setSelectionRange(start, end)\n // Intentional use of deprecated: https://developer.mozilla.org/docs/Web/API/Document/execCommand#using_inserttext\n document.execCommand('insertText', false, updatedText)\n inputField.setSelectionRange(start, start + updatedText.length)\n }\n window.addEventListener('keydown', editAttention)\n }\n})\n","interface UVMirror {\n /**\n * The setting id defined for the mirror.\n */\n settingId: string\n /**\n * The default mirror to use.\n */\n mirror: string\n /**\n * The fallback mirror to use.\n */\n fallbackMirror: string\n /**\n * The path suffix to validate the mirror is reachable.\n */\n validationPathSuffix?: string\n}\n\nexport const PYTHON_MIRROR: UVMirror = {\n settingId: 'Comfy-Desktop.UV.PythonInstallMirror',\n mirror:\n 'https://github.com/astral-sh/python-build-standalone/releases/download',\n fallbackMirror:\n 'https://python-standalone.org/mirror/astral-sh/python-build-standalone',\n validationPathSuffix:\n '/20250115/cpython-3.10.16+20250115-aarch64-apple-darwin-debug-full.tar.zst.sha256'\n}\n","import { electronAPI } from '@/utils/envUtil'\nimport { isValidUrl } from '@/utils/formatUtil'\n\n/**\n * Check if a mirror is reachable from the electron App.\n * @param mirror - The mirror to check.\n * @returns True if the mirror is reachable, false otherwise.\n */\nexport const checkMirrorReachable = async (mirror: string) => {\n return (\n isValidUrl(mirror) && (await electronAPI().NetWork.canAccessUrl(mirror))\n )\n}\n","import log from 'loglevel'\n\nimport { useExternalLink } from '@/composables/useExternalLink'\nimport { PYTHON_MIRROR } from '@/constants/uvMirrors'\nimport { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'\nimport { app } from '@/scripts/app'\nimport { useDialogService } from '@/services/dialogService'\nimport { checkMirrorReachable } from '@/utils/electronMirrorCheck'\nimport { electronAPI as getElectronAPI, isElectron } from '@/utils/envUtil'\n;(async () => {\n if (!isElectron()) return\n\n const electronAPI = getElectronAPI()\n const desktopAppVersion = await electronAPI.getElectronVersion()\n const workflowStore = useWorkflowStore()\n const toastStore = useToastStore()\n const { staticUrls, buildDocsUrl } = useExternalLink()\n\n const onChangeRestartApp = (newValue: string, oldValue: string) => {\n // Add a delay to allow changes to take effect before restarting.\n if (oldValue !== undefined && newValue !== oldValue) {\n electronAPI.restartApp('Restart ComfyUI to apply changes.', 1500)\n }\n }\n\n app.registerExtension({\n name: 'Comfy.ElectronAdapter',\n settings: [\n {\n id: 'Comfy-Desktop.AutoUpdate',\n category: ['Comfy-Desktop', 'General', 'AutoUpdate'],\n name: 'Automatically check for updates',\n type: 'boolean',\n defaultValue: true,\n onChange: onChangeRestartApp\n },\n {\n id: 'Comfy-Desktop.SendStatistics',\n category: ['Comfy-Desktop', 'General', 'Send Statistics'],\n name: 'Send anonymous usage metrics',\n type: 'boolean',\n defaultValue: true,\n onChange: onChangeRestartApp\n },\n {\n id: 'Comfy-Desktop.WindowStyle',\n category: ['Comfy-Desktop', 'General', 'Window Style'],\n name: 'Window Style',\n tooltip: \"Custom: Replace the system title bar with ComfyUI's Top menu\",\n type: 'combo',\n experimental: true,\n defaultValue: 'default',\n options: ['default', 'custom'],\n onChange: (\n newValue: 'default' | 'custom',\n oldValue?: 'default' | 'custom'\n ) => {\n if (!oldValue) return\n\n electronAPI.Config.setWindowStyle(newValue)\n }\n },\n {\n id: 'Comfy-Desktop.UV.PythonInstallMirror',\n name: 'Python Install Mirror',\n tooltip: `Managed Python installations are downloaded from the Astral python-build-standalone project. This variable can be set to a mirror URL to use a different source for Python installations. The provided URL will replace https://github.com/astral-sh/python-build-standalone/releases/download in, e.g., https://github.com/astral-sh/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz. Distributions can be read from a local directory by using the file:// URL scheme.`,\n type: 'url',\n defaultValue: '',\n attrs: {\n validateUrlFn(mirror: string) {\n return checkMirrorReachable(\n mirror + PYTHON_MIRROR.validationPathSuffix\n )\n }\n }\n },\n {\n id: 'Comfy-Desktop.UV.PypiInstallMirror',\n name: 'Pypi Install Mirror',\n tooltip: `Default pip install mirror`,\n type: 'url',\n defaultValue: '',\n attrs: {\n validateUrlFn: checkMirrorReachable\n }\n },\n {\n id: 'Comfy-Desktop.UV.TorchInstallMirror',\n name: 'Torch Install Mirror',\n tooltip: `Pip install mirror for pytorch`,\n type: 'url',\n defaultValue: '',\n attrs: {\n validateUrlFn: checkMirrorReachable\n }\n }\n ],\n\n commands: [\n {\n id: 'Comfy-Desktop.Folders.OpenLogsFolder',\n label: 'Open Logs Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openLogsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenModelsFolder',\n label: 'Open Models Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openModelsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenOutputsFolder',\n label: 'Open Outputs Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openOutputsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenInputsFolder',\n label: 'Open Inputs Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openInputsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenCustomNodesFolder',\n label: 'Open Custom Nodes Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openCustomNodesFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenModelConfig',\n label: 'Open extra_model_paths.yaml',\n icon: 'pi pi-file',\n function() {\n electronAPI.openModelConfig()\n }\n },\n {\n id: 'Comfy-Desktop.OpenDevTools',\n label: 'Open DevTools',\n icon: 'pi pi-code',\n function() {\n electronAPI.openDevTools()\n }\n },\n {\n id: 'Comfy-Desktop.OpenUserGuide',\n label: 'Desktop User Guide',\n icon: 'pi pi-book',\n function() {\n window.open(\n buildDocsUrl('/installation/desktop', {\n includeLocale: true,\n platform: true\n }),\n '_blank'\n )\n }\n },\n {\n id: 'Comfy-Desktop.CheckForUpdates',\n label: 'Check for Updates',\n icon: 'pi pi-sync',\n async function() {\n try {\n const updateInfo = await electronAPI.checkForUpdates({\n disableUpdateReadyAction: true\n })\n\n if (!updateInfo.isUpdateAvailable) {\n toastStore.add({\n severity: 'info',\n summary: t('desktopUpdate.noUpdateFound'),\n life: 5_000\n })\n return\n }\n\n const proceed = await useDialogService().confirm({\n title: t('desktopUpdate.updateFoundTitle', {\n version: updateInfo.version\n }),\n message: t('desktopUpdate.updateAvailableMessage'),\n type: 'default'\n })\n if (proceed) {\n try {\n electronAPI.restartAndInstall()\n } catch (error) {\n log.error('Error installing update:', error)\n toastStore.add({\n severity: 'error',\n summary: t('g.error'),\n detail: t('desktopUpdate.errorInstallingUpdate'),\n life: 10_000\n })\n }\n }\n } catch (error) {\n log.error('Error checking for updates:', error)\n toastStore.add({\n severity: 'error',\n summary: t('g.error'),\n detail: t('desktopUpdate.errorCheckingUpdate'),\n life: 10_000\n })\n }\n }\n },\n {\n id: 'Comfy-Desktop.Reinstall',\n label: 'Reinstall',\n icon: 'pi pi-refresh',\n async function() {\n const proceed = await useDialogService().confirm({\n message: t('desktopMenu.confirmReinstall'),\n title: t('desktopMenu.reinstall'),\n type: 'reinstall'\n })\n\n if (proceed) electronAPI.reinstall()\n }\n },\n {\n id: 'Comfy-Desktop.Restart',\n label: 'Restart',\n icon: 'pi pi-refresh',\n function() {\n electronAPI.restartApp()\n }\n },\n {\n id: 'Comfy-Desktop.Quit',\n label: 'Quit',\n icon: 'pi pi-sign-out',\n async function() {\n // Confirm if unsaved workflows are open\n if (workflowStore.modifiedWorkflows.length > 0) {\n const confirmed = await useDialogService().confirm({\n message: t('desktopMenu.confirmQuit'),\n title: t('desktopMenu.quit'),\n type: 'default'\n })\n\n if (!confirmed) return\n }\n\n electronAPI.quit()\n }\n }\n ],\n\n menuCommands: [\n {\n path: ['Help'],\n commands: ['Comfy-Desktop.OpenUserGuide']\n },\n {\n path: ['Help'],\n commands: ['Comfy-Desktop.OpenDevTools']\n },\n {\n path: ['Help', 'Open Folder'],\n commands: [\n 'Comfy-Desktop.Folders.OpenLogsFolder',\n 'Comfy-Desktop.Folders.OpenModelsFolder',\n 'Comfy-Desktop.Folders.OpenOutputsFolder',\n 'Comfy-Desktop.Folders.OpenInputsFolder',\n 'Comfy-Desktop.Folders.OpenCustomNodesFolder',\n 'Comfy-Desktop.Folders.OpenModelConfig'\n ]\n },\n {\n path: ['Help'],\n commands: ['Comfy-Desktop.CheckForUpdates', 'Comfy-Desktop.Reinstall']\n }\n ],\n\n keybindings: [\n {\n commandId: 'Workspace.CloseWorkflow',\n combo: {\n key: 'w',\n ctrl: true\n }\n }\n ],\n\n aboutPageBadges: [\n {\n label: 'ComfyUI_desktop v' + desktopAppVersion,\n url: staticUrls.githubElectron,\n icon: 'pi pi-github'\n }\n ]\n })\n})()\n","import type { GroupNodeHandler } from '@/extensions/core/groupNode'\nimport { ExecutableNodeDTO } from '@/lib/litegraph/src/litegraph'\nimport type {\n ExecutableLGraphNode,\n ExecutionId,\n LGraphNode,\n NodeId,\n SubgraphNode\n} from '@/lib/litegraph/src/litegraph'\n\nexport class ExecutableGroupNodeChildDTO extends ExecutableNodeDTO {\n groupNodeHandler?: GroupNodeHandler\n\n constructor(\n /** The actual node that this DTO wraps. */\n node: LGraphNode | SubgraphNode,\n /** A list of subgraph instance node IDs from the root graph to the containing instance. @see {@link id} */\n subgraphNodePath: readonly NodeId[],\n /** A flattened map of all DTOs in this node network. Subgraph instances have been expanded into their inner nodes. */\n nodesByExecutionId: Map<ExecutionId, ExecutableLGraphNode>,\n /** The actual subgraph instance that contains this node, otherwise undefined. */\n subgraphNode?: SubgraphNode | undefined,\n groupNodeHandler?: GroupNodeHandler\n ) {\n super(node, subgraphNodePath, nodesByExecutionId, subgraphNode)\n this.groupNodeHandler = groupNodeHandler\n }\n\n override resolveInput(slot: number) {\n // Check if this group node is inside a subgraph (unsupported)\n if (this.id.split(':').length > 2) {\n throw new Error(\n 'Group nodes inside subgraphs are not supported. Please convert the group node to a subgraph instead.'\n )\n }\n\n const inputNode = this.node.getInputNode(slot)\n if (!inputNode) return\n\n const link = this.node.getInputLink(slot)\n if (!link) throw new Error('Failed to get input link')\n\n const inputNodeId = String(inputNode.id)\n\n // Try to find the node using the full ID first (for nodes outside the group)\n let inputNodeDto = this.nodesByExecutionId?.get(inputNodeId)\n\n // If not found, try with just the last part of the ID (for nodes inside the group)\n if (!inputNodeDto) {\n const id = inputNodeId.split(':').at(-1)\n if (id !== undefined) {\n inputNodeDto = this.nodesByExecutionId?.get(id)\n }\n }\n\n if (!inputNodeDto) {\n throw new Error(\n `Failed to get input node ${inputNodeId} for group node child ${this.id} with slot ${slot}`\n )\n }\n\n return {\n node: inputNodeDto,\n origin_id: inputNodeId,\n origin_slot: link.origin_slot\n }\n }\n}\n","import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants'\nimport {\n type LGraphNode,\n type LGraphNodeConstructor,\n LiteGraph\n} from '@/lib/litegraph/src/litegraph'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\n\nimport { type ComfyApp, app } from '../../scripts/app'\nimport { $el } from '../../scripts/ui'\nimport { ComfyDialog } from '../../scripts/ui/dialog'\nimport { DraggableList } from '../../scripts/ui/draggableList'\nimport { GroupNodeConfig, GroupNodeHandler } from './groupNode'\nimport './groupNodeManage.css'\n\nconst ORDER: symbol = Symbol()\n\n// @ts-expect-error fixme ts strict error\nfunction merge(target, source) {\n if (typeof target === 'object' && typeof source === 'object') {\n for (const key in source) {\n const sv = source[key]\n if (typeof sv === 'object') {\n let tv = target[key]\n if (!tv) tv = target[key] = {}\n merge(tv, source[key])\n } else {\n target[key] = sv\n }\n }\n }\n\n return target\n}\n\nexport class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {\n // @ts-expect-error fixme ts strict error\n tabs: Record<\n 'Inputs' | 'Outputs' | 'Widgets',\n { tab: HTMLAnchorElement; page: HTMLElement }\n >\n selectedNodeIndex: number | null | undefined\n selectedTab: keyof ManageGroupDialog['tabs'] = 'Inputs'\n selectedGroup: string | undefined\n modifications: Record<\n string,\n Record<\n string,\n Record<\n string,\n { name?: string | undefined; visible?: boolean | undefined }\n >\n >\n > = {}\n // @ts-expect-error fixme ts strict error\n nodeItems: any[]\n app: ComfyApp\n // @ts-expect-error fixme ts strict error\n groupNodeType: LGraphNodeConstructor<LGraphNode>\n groupNodeDef: any\n groupData: any\n\n // @ts-expect-error fixme ts strict error\n innerNodesList: HTMLUListElement\n // @ts-expect-error fixme ts strict error\n widgetsPage: HTMLElement\n // @ts-expect-error fixme ts strict error\n inputsPage: HTMLElement\n // @ts-expect-error fixme ts strict error\n outputsPage: HTMLElement\n draggable: any\n\n get selectedNodeInnerIndex() {\n // @ts-expect-error fixme ts strict error\n return +this.nodeItems[this.selectedNodeIndex].dataset.nodeindex\n }\n\n // @ts-expect-error fixme ts strict error\n constructor(app) {\n super()\n this.app = app\n this.element = $el('dialog.comfy-group-manage', {\n parent: document.body\n }) as HTMLDialogElement\n }\n\n // @ts-expect-error fixme ts strict error\n changeTab(tab) {\n this.tabs[this.selectedTab].tab.classList.remove('active')\n this.tabs[this.selectedTab].page.classList.remove('active')\n // @ts-expect-error fixme ts strict error\n this.tabs[tab].tab.classList.add('active')\n // @ts-expect-error fixme ts strict error\n this.tabs[tab].page.classList.add('active')\n this.selectedTab = tab\n }\n\n // @ts-expect-error fixme ts strict error\n changeNode(index, force?) {\n if (!force && this.selectedNodeIndex === index) return\n\n if (this.selectedNodeIndex != null) {\n this.nodeItems[this.selectedNodeIndex].classList.remove('selected')\n }\n this.nodeItems[index].classList.add('selected')\n this.selectedNodeIndex = index\n\n if (!this.buildInputsPage() && this.selectedTab === 'Inputs') {\n this.changeTab('Widgets')\n }\n if (!this.buildWidgetsPage() && this.selectedTab === 'Widgets') {\n this.changeTab('Outputs')\n }\n if (!this.buildOutputsPage() && this.selectedTab === 'Outputs') {\n this.changeTab('Inputs')\n }\n\n this.changeTab(this.selectedTab)\n }\n\n getGroupData() {\n this.groupNodeType = LiteGraph.registered_node_types[\n `${PREFIX}${SEPARATOR}` + this.selectedGroup\n ] as unknown as LGraphNodeConstructor<LGraphNode>\n this.groupNodeDef = this.groupNodeType.nodeData\n this.groupData = GroupNodeHandler.getGroupData(this.groupNodeType)\n }\n\n // @ts-expect-error fixme ts strict error\n changeGroup(group, reset = true) {\n this.selectedGroup = group\n this.getGroupData()\n\n const nodes = this.groupData.nodeData.nodes\n // @ts-expect-error fixme ts strict error\n this.nodeItems = nodes.map((n, i) =>\n $el(\n 'li.draggable-item',\n {\n dataset: {\n nodeindex: n.index + ''\n },\n onclick: () => {\n this.changeNode(i)\n }\n },\n [\n $el('span.drag-handle'),\n $el(\n 'div',\n {\n textContent: n.title ?? n.type\n },\n n.title\n ? $el('span', {\n textContent: n.type\n })\n : []\n )\n ]\n )\n )\n\n this.innerNodesList.replaceChildren(...this.nodeItems)\n\n if (reset) {\n this.selectedNodeIndex = null\n this.changeNode(0)\n } else {\n const items = this.draggable.getAllItems()\n // @ts-expect-error fixme ts strict error\n let index = items.findIndex((item) => item.classList.contains('selected'))\n if (index === -1) index = this.selectedNodeIndex\n this.changeNode(index, true)\n }\n\n const ordered = [...nodes]\n this.draggable?.dispose()\n this.draggable = new DraggableList(this.innerNodesList, 'li')\n this.draggable.addEventListener(\n 'dragend',\n // @ts-expect-error fixme ts strict error\n ({ detail: { oldPosition, newPosition } }) => {\n if (oldPosition === newPosition) return\n ordered.splice(newPosition, 0, ordered.splice(oldPosition, 1)[0])\n for (let i = 0; i < ordered.length; i++) {\n this.storeModification({\n nodeIndex: ordered[i].index,\n section: ORDER,\n prop: 'order',\n value: i\n })\n }\n }\n )\n }\n\n storeModification(props: {\n nodeIndex?: number\n section: symbol\n prop: string\n value: any\n }) {\n const { nodeIndex, section, prop, value } = props\n // @ts-expect-error fixme ts strict error\n const groupMod = (this.modifications[this.selectedGroup] ??= {})\n const nodesMod = (groupMod.nodes ??= {})\n const nodeMod = (nodesMod[nodeIndex ?? this.selectedNodeInnerIndex] ??= {})\n const typeMod = (nodeMod[section] ??= {})\n if (typeof value === 'object') {\n const objMod = (typeMod[prop] ??= {})\n Object.assign(objMod, value)\n } else {\n typeMod[prop] = value\n }\n }\n\n // @ts-expect-error fixme ts strict error\n getEditElement(section, prop, value, placeholder, checked, checkable = true) {\n if (value === placeholder) value = ''\n\n const mods =\n // @ts-expect-error fixme ts strict error\n this.modifications[this.selectedGroup]?.nodes?.[\n this.selectedNodeInnerIndex\n ]?.[section]?.[prop]\n if (mods) {\n if (mods.name != null) {\n value = mods.name\n }\n if (mods.visible != null) {\n checked = mods.visible\n }\n }\n\n return $el('div', [\n $el('input', {\n value,\n placeholder,\n type: 'text',\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n this.storeModification({\n section,\n prop,\n value: { name: e.target.value }\n })\n }\n }),\n $el('label', { textContent: 'Visible' }, [\n $el('input', {\n type: 'checkbox',\n checked,\n disabled: !checkable,\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n this.storeModification({\n section,\n prop,\n value: { visible: !!e.target.checked }\n })\n }\n })\n ])\n ])\n }\n\n buildWidgetsPage() {\n const widgets =\n this.groupData.oldToNewWidgetMap[this.selectedNodeInnerIndex]\n const items = Object.keys(widgets ?? {})\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[this.selectedGroup]\n const config = type.config?.[this.selectedNodeInnerIndex]?.input\n this.widgetsPage.replaceChildren(\n ...items.map((oldName) => {\n return this.getEditElement(\n 'input',\n oldName,\n widgets[oldName],\n oldName,\n config?.[oldName]?.visible !== false\n )\n })\n )\n return !!items.length\n }\n\n buildInputsPage() {\n const inputs = this.groupData.nodeInputs[this.selectedNodeInnerIndex]\n const items = Object.keys(inputs ?? {})\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[this.selectedGroup]\n const config = type.config?.[this.selectedNodeInnerIndex]?.input\n this.inputsPage.replaceChildren(\n // @ts-expect-error fixme ts strict error\n ...items\n .map((oldName) => {\n let value = inputs[oldName]\n if (!value) {\n return\n }\n\n return this.getEditElement(\n 'input',\n oldName,\n value,\n oldName,\n config?.[oldName]?.visible !== false\n )\n })\n .filter(Boolean)\n )\n return !!items.length\n }\n\n buildOutputsPage() {\n const nodes = this.groupData.nodeData.nodes\n const innerNodeDef = this.groupData.getNodeDef(\n nodes[this.selectedNodeInnerIndex]\n )\n const outputs = innerNodeDef?.output ?? []\n const groupOutputs =\n this.groupData.oldToNewOutputMap[this.selectedNodeInnerIndex]\n\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[this.selectedGroup]\n const config = type.config?.[this.selectedNodeInnerIndex]?.output\n const node = this.groupData.nodeData.nodes[this.selectedNodeInnerIndex]\n const checkable = node.type !== 'PrimitiveNode'\n this.outputsPage.replaceChildren(\n ...outputs\n // @ts-expect-error fixme ts strict error\n .map((type, slot) => {\n const groupOutputIndex = groupOutputs?.[slot]\n const oldName = innerNodeDef.output_name?.[slot] ?? type\n let value = config?.[slot]?.name\n const visible = config?.[slot]?.visible || groupOutputIndex != null\n if (!value || value === oldName) {\n value = ''\n }\n return this.getEditElement(\n 'output',\n slot,\n value,\n oldName,\n visible,\n checkable\n )\n })\n .filter(Boolean)\n )\n return !!outputs.length\n }\n\n // @ts-expect-error fixme ts strict error\n show(type?) {\n const groupNodes = Object.keys(app.rootGraph.extra?.groupNodes ?? {}).sort(\n (a, b) => a.localeCompare(b)\n )\n\n this.innerNodesList = $el(\n 'ul.comfy-group-manage-list-items'\n ) as HTMLUListElement\n this.widgetsPage = $el('section.comfy-group-manage-node-page')\n this.inputsPage = $el('section.comfy-group-manage-node-page')\n this.outputsPage = $el('section.comfy-group-manage-node-page')\n const pages = $el('div', [\n this.widgetsPage,\n this.inputsPage,\n this.outputsPage\n ])\n\n this.tabs = [\n ['Inputs', this.inputsPage],\n ['Widgets', this.widgetsPage],\n ['Outputs', this.outputsPage]\n // @ts-expect-error fixme ts strict error\n ].reduce((p, [name, page]: [string, HTMLElement]) => {\n // @ts-expect-error fixme ts strict error\n p[name] = {\n tab: $el('a', {\n onclick: () => {\n this.changeTab(name)\n },\n textContent: name\n }),\n page\n }\n return p\n }, {}) as any\n\n const outer = $el('div.comfy-group-manage-outer', [\n $el('header', [\n $el('h2', 'Group Nodes'),\n $el(\n 'select',\n {\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n this.changeGroup(e.target.value)\n }\n },\n groupNodes.map((g) =>\n $el('option', {\n textContent: g,\n selected: `${PREFIX}${SEPARATOR}${g}` === type,\n value: g\n })\n )\n )\n ]),\n $el('main', [\n $el('section.comfy-group-manage-list', this.innerNodesList),\n $el('section.comfy-group-manage-node', [\n $el(\n 'header',\n Object.values(this.tabs).map((t) => t.tab)\n ),\n pages\n ])\n ]),\n $el('footer', [\n $el(\n 'button.comfy-btn',\n {\n onclick: () => {\n const node = app.rootGraph.nodes.find(\n (n) => n.type === `${PREFIX}${SEPARATOR}` + this.selectedGroup\n )\n if (node) {\n useToastStore().addAlert(\n 'This group node is in use in the current workflow, please first remove these.'\n )\n return\n }\n if (\n confirm(\n `Are you sure you want to remove the node: \"${this.selectedGroup}\"`\n )\n ) {\n // @ts-expect-error fixme ts strict error\n delete app.rootGraph.extra.groupNodes[this.selectedGroup]\n LiteGraph.unregisterNodeType(\n `${PREFIX}${SEPARATOR}` + this.selectedGroup\n )\n }\n this.show()\n }\n },\n 'Delete Group Node'\n ),\n $el(\n 'button.comfy-btn',\n {\n onclick: async () => {\n let nodesByType\n let recreateNodes = []\n const types = {}\n for (const g in this.modifications) {\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[g]\n let config = (type.config ??= {})\n\n let nodeMods = this.modifications[g]?.nodes\n if (nodeMods) {\n const keys = Object.keys(nodeMods)\n // @ts-expect-error fixme ts strict error\n if (nodeMods[keys[0]][ORDER]) {\n // If any node is reordered, they will all need sequencing\n const orderedNodes = []\n const orderedMods = {}\n const orderedConfig = {}\n\n for (const n of keys) {\n // @ts-expect-error fixme ts strict error\n const order = nodeMods[n][ORDER].order\n orderedNodes[order] = type.nodes[+n]\n // @ts-expect-error fixme ts strict error\n orderedMods[order] = nodeMods[n]\n orderedNodes[order].index = order\n }\n\n // Rewrite links\n for (const l of type.links) {\n if (l[0] != null) l[0] = type.nodes[l[0]].index\n if (l[2] != null) l[2] = type.nodes[l[2]].index\n }\n\n // Rewrite externals\n if (type.external) {\n for (const ext of type.external) {\n ext[0] = type.nodes[ext[0]]\n }\n }\n\n // Rewrite modifications\n for (const id of keys) {\n if (config[id]) {\n // @ts-expect-error fixme ts strict error\n orderedConfig[type.nodes[id].index] = config[id]\n }\n delete config[id]\n }\n\n type.nodes = orderedNodes\n nodeMods = orderedMods\n type.config = config = orderedConfig\n }\n\n merge(config, nodeMods)\n }\n\n // @ts-expect-error fixme ts strict error\n types[g] = type\n\n if (!nodesByType) {\n nodesByType = app.rootGraph.nodes.reduce((p, n) => {\n // @ts-expect-error fixme ts strict error\n p[n.type] ??= []\n // @ts-expect-error fixme ts strict error\n p[n.type].push(n)\n return p\n }, {})\n }\n\n // @ts-expect-error fixme ts strict error\n const nodes = nodesByType[`${PREFIX}${SEPARATOR}` + g]\n if (nodes) recreateNodes.push(...nodes)\n }\n\n await GroupNodeConfig.registerFromWorkflow(types, {})\n\n for (const node of recreateNodes) {\n node.recreate()\n }\n\n this.modifications = {}\n this.app.canvas.setDirty(true, true)\n this.changeGroup(this.selectedGroup, false)\n }\n },\n 'Save'\n ),\n $el(\n 'button.comfy-btn',\n { onclick: () => this.element.close() },\n 'Close'\n )\n ])\n ])\n\n this.element.replaceChildren(outer)\n this.changeGroup(\n type\n ? (groupNodes.find((g) => `${PREFIX}${SEPARATOR}${g}` === type) ??\n groupNodes[0])\n : groupNodes[0]\n )\n this.element.showModal()\n\n this.element.addEventListener('close', () => {\n this.draggable?.dispose()\n this.element.remove()\n })\n }\n}\n","import _ from 'es-toolkit/compat'\n\nimport type {\n ComboInputSpec,\n ComboInputSpecV2,\n FloatInputSpec,\n InputSpec,\n IntInputSpec,\n NumericInputOptions\n} from '@/schemas/nodeDefSchema'\nimport {\n getComboSpecComboOptions,\n getInputSpecType,\n isComboInputSpec,\n isFloatInputSpec,\n isIntInputSpec\n} from '@/schemas/nodeDefSchema'\n\nimport { lcm } from './mathUtil'\n\nconst IGNORE_KEYS = new Set<string>([\n 'default',\n 'forceInput',\n 'defaultInput',\n 'control_after_generate',\n 'multiline',\n 'tooltip',\n 'dynamicPrompts'\n])\n\nconst getRange = (options: NumericInputOptions) => {\n const min = options.min ?? -Infinity\n const max = options.max ?? Infinity\n return { min, max }\n}\n\nconst mergeNumericInputSpec = <T extends IntInputSpec | FloatInputSpec>(\n spec1: T,\n spec2: T\n): T | null => {\n const type = spec1[0]\n const options1 = spec1[1] ?? {}\n const options2 = spec2[1] ?? {}\n\n const range1 = getRange(options1)\n const range2 = getRange(options2)\n\n // If the ranges do not overlap, return null\n if (range1.min > range2.max || range1.max < range2.min) {\n return null\n }\n\n const step1 = options1.step ?? 1\n const step2 = options2.step ?? 1\n\n const mergedOptions = {\n // Take intersection of ranges\n min: Math.max(range1.min, range2.min),\n max: Math.min(range1.max, range2.max),\n step: lcm(step1, step2)\n }\n\n return mergeCommonInputSpec(\n [type, { ...options1, ...mergedOptions }] as T,\n [type, { ...options2, ...mergedOptions }] as T\n )\n}\n\nconst mergeComboInputSpec = <T extends ComboInputSpec | ComboInputSpecV2>(\n spec1: T,\n spec2: T\n): T | null => {\n const options1 = spec1[1] ?? {}\n const options2 = spec2[1] ?? {}\n\n const comboOptions1 = getComboSpecComboOptions(spec1)\n const comboOptions2 = getComboSpecComboOptions(spec2)\n\n const intersection = _.intersection(comboOptions1, comboOptions2)\n\n // If the intersection is empty, return null\n if (intersection.length === 0) {\n return null\n }\n\n return mergeCommonInputSpec(\n ['COMBO', { ...options1, options: intersection }] as T,\n ['COMBO', { ...options2, options: intersection }] as T\n )\n}\n\nconst mergeCommonInputSpec = <T extends InputSpec>(\n spec1: T,\n spec2: T\n): T | null => {\n const type = getInputSpecType(spec1)\n const options1 = spec1[1] ?? {}\n const options2 = spec2[1] ?? {}\n\n const compareKeys = _.union(_.keys(options1), _.keys(options2)).filter(\n (key) => !IGNORE_KEYS.has(key)\n )\n\n const mergeIsValid = compareKeys.every((key) => {\n const value1 = options1[key]\n const value2 = options2[key]\n return value1 === value2 || (_.isNil(value1) && _.isNil(value2))\n })\n\n return mergeIsValid ? ([type, { ...options1, ...options2 }] as T) : null\n}\n\n/**\n * Merges two input specs.\n *\n * @param spec1 - The first input spec.\n * @param spec2 - The second input spec.\n * @returns The merged input spec, or null if the specs are not mergeable.\n */\nexport const mergeInputSpec = (\n spec1: InputSpec,\n spec2: InputSpec\n): InputSpec | null => {\n const type1 = getInputSpecType(spec1)\n const type2 = getInputSpecType(spec2)\n\n if (type1 !== type2) {\n return null\n }\n\n if (isIntInputSpec(spec1) || isFloatInputSpec(spec1)) {\n return mergeNumericInputSpec(spec1, spec2 as typeof spec1)\n }\n\n if (isComboInputSpec(spec1)) {\n return mergeComboInputSpec(spec1, spec2 as typeof spec1)\n }\n\n return mergeCommonInputSpec(spec1, spec2)\n}\n","import type { PrimitiveNode } from '@/extensions/core/widgetInputs'\nimport type { LGraphNode } from '@/lib/litegraph/src/litegraph'\n\nexport const isPrimitiveNode = (\n node: LGraphNode\n): node is PrimitiveNode & LGraphNode => node.type === 'PrimitiveNode'\n","import {\n type CallbackParams,\n useChainCallback\n} from '@/composables/functional/useChainCallback'\nimport { LGraphNode, LiteGraph } from '@/lib/litegraph/src/litegraph'\nimport type {\n INodeInputSlot,\n INodeOutputSlot,\n ISlotType,\n LLink\n} from '@/lib/litegraph/src/litegraph'\nimport { NodeSlot } from '@/lib/litegraph/src/node/NodeSlot'\nimport type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'\nimport type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'\nimport type { InputSpec } from '@/schemas/nodeDefSchema'\nimport { app } from '@/scripts/app'\nimport {\n ComfyWidgets,\n addValueControlWidgets,\n isValidWidgetType\n} from '@/scripts/widgets'\nimport { CONFIG, GET_CONFIG } from '@/services/litegraphService'\nimport { mergeInputSpec } from '@/utils/nodeDefUtil'\nimport { applyTextReplacements } from '@/utils/searchAndReplace'\nimport { isPrimitiveNode } from '@/renderer/utils/nodeTypeGuards'\n\nconst replacePropertyName = 'Run widget replace on values'\nexport class PrimitiveNode extends LGraphNode {\n controlValues?: any[]\n lastType?: string\n static override category: string\n constructor(title: string) {\n super(title)\n this.addOutput('connect to widget input', '*')\n this.serialize_widgets = true\n this.isVirtualNode = true\n\n if (!this.properties || !(replacePropertyName in this.properties)) {\n this.addProperty(replacePropertyName, false, 'boolean')\n }\n }\n\n override applyToGraph(extraLinks: LLink[] = []) {\n if (!this.outputs[0].links?.length || !this.graph) return\n\n const links = [\n ...this.outputs[0].links.map((l) => this.graph!.links[l]),\n ...extraLinks\n ]\n let v = this.widgets?.[0].value\n if (v && this.properties[replacePropertyName]) {\n v = applyTextReplacements(this.graph, v as string)\n }\n\n // For each output link copy our value over the original widget value\n for (const linkInfo of links) {\n const node = this.graph?.getNodeById(linkInfo.target_id)\n const input = node?.inputs[linkInfo.target_slot]\n if (!input) {\n console.warn('Unable to resolve node or input for link', linkInfo)\n continue\n }\n\n const widgetName = input.widget?.name\n if (!widgetName) {\n console.warn('Invalid widget or widget name', input.widget)\n continue\n }\n\n const widget = node.widgets?.find((w) => w.name === widgetName)\n if (!widget) {\n console.warn(\n `Unable to find widget \"${widgetName}\" on node [${node.id}]`\n )\n continue\n }\n\n widget.value = v\n widget.callback?.(\n widget.value,\n app.canvas,\n node,\n app.canvas.graph_mouse,\n {} as CanvasPointerEvent\n )\n }\n }\n\n override refreshComboInNode() {\n const widget = this.widgets?.[0]\n if (widget?.type === 'combo') {\n // @ts-expect-error fixme ts strict error\n widget.options.values = this.outputs[0].widget[GET_CONFIG]()[0]\n\n // @ts-expect-error fixme ts strict error\n if (!widget.options.values.includes(widget.value as string)) {\n // @ts-expect-error fixme ts strict error\n widget.value = widget.options.values[0]\n ;(widget.callback as Function)(widget.value)\n }\n }\n }\n\n override onAfterGraphConfigured() {\n if (this.outputs[0].links?.length && !this.widgets?.length) {\n this.#onFirstConnection()\n\n // Populate widget values from config data\n if (this.widgets && this.widgets_values) {\n for (let i = 0; i < this.widgets_values.length; i++) {\n const w = this.widgets[i]\n if (w) {\n w.value = this.widgets_values[i] as any\n }\n }\n }\n\n // Merge values if required\n this.#mergeWidgetConfig()\n }\n }\n\n override onConnectionsChange(\n _type: ISlotType,\n _index: number,\n connected: boolean\n ) {\n if (app.configuringGraph) {\n // Dont run while the graph is still setting up\n return\n }\n\n const links = this.outputs[0].links\n if (connected) {\n if (links?.length && !this.widgets?.length) {\n this.#onFirstConnection()\n }\n } else {\n // We may have removed a link that caused the constraints to change\n this.#mergeWidgetConfig()\n\n if (!links?.length) {\n this.onLastDisconnect()\n }\n }\n }\n\n override onConnectOutput(\n slot: number,\n _type: string,\n input: INodeInputSlot,\n target_node: LGraphNode,\n target_slot: number\n ) {\n // Fires before the link is made allowing us to reject it if it isn't valid\n // No widget, we can't connect\n if (!input.widget && !(input.type in ComfyWidgets)) {\n return false\n }\n\n if (this.outputs[slot].links?.length) {\n const valid = this.#isValidConnection(input)\n if (valid) {\n // On connect of additional outputs, copy our value to their widget\n this.applyToGraph([{ target_id: target_node.id, target_slot } as LLink])\n }\n return valid\n }\n\n return true\n }\n\n #onFirstConnection(recreating?: boolean) {\n // First connection can fire before the graph is ready on initial load so random things can be missing\n if (!this.outputs[0].links || !this.graph) {\n this.onLastDisconnect()\n return\n }\n const linkId = this.outputs[0].links[0]\n const link = this.graph.links[linkId]\n if (!link) return\n\n const theirNode = this.graph.getNodeById(link.target_id)\n if (!theirNode || !theirNode.inputs) return\n\n const input = theirNode.inputs[link.target_slot]\n if (!input) return\n\n let widget\n if (!input.widget) {\n if (!(input.type in ComfyWidgets)) return\n widget = { name: input.name, [GET_CONFIG]: () => [input.type, {}] } //fake widget\n } else {\n widget = input.widget\n }\n\n // @ts-expect-error fixme ts strict error\n const config = widget[GET_CONFIG]?.()\n if (!config) return\n\n const { type } = getWidgetType(config)\n // Update our output to restrict to the widget type\n this.outputs[0].type = type\n this.outputs[0].name = type\n this.outputs[0].widget = widget\n\n this.#createWidget(\n widget[CONFIG] ?? config,\n theirNode,\n widget.name,\n // @ts-expect-error fixme ts strict error\n recreating\n )\n }\n\n #createWidget(\n inputData: InputSpec,\n node: LGraphNode,\n widgetName: string,\n recreating: boolean\n ) {\n let type = inputData[0]\n\n if (type instanceof Array) {\n type = 'COMBO'\n }\n\n // Store current size as addWidget resizes the node\n const [oldWidth, oldHeight] = this.size\n let widget: IBaseWidget\n if (isValidWidgetType(type)) {\n widget = (ComfyWidgets[type](this, 'value', inputData, app) || {}).widget\n } else {\n // @ts-expect-error InputSpec is not typed correctly\n widget = this.addWidget(type, 'value', null, () => {}, {})\n }\n\n if (node?.widgets && widget) {\n const theirWidget = node.widgets.find((w) => w.name === widgetName)\n if (theirWidget) {\n widget.value = theirWidget.value\n }\n }\n\n if (\n !inputData?.[1]?.control_after_generate &&\n (widget.type === 'number' || widget.type === 'combo')\n ) {\n let control_value = this.widgets_values?.[1]\n if (!control_value) {\n control_value = 'fixed'\n }\n addValueControlWidgets(\n this,\n widget,\n control_value as string,\n undefined,\n inputData\n )\n if (this.widgets?.[1]) widget.linkedWidgets = [this.widgets[1]]\n\n let filter = this.widgets_values?.[2]\n if (filter && this.widgets && this.widgets.length === 3) {\n this.widgets[2].value = filter\n }\n }\n\n // Restore any saved control values\n const controlValues = this.controlValues\n if (\n this.widgets &&\n this.lastType === this.widgets[0]?.type &&\n controlValues?.length === this.widgets.length - 1\n ) {\n for (let i = 0; i < controlValues.length; i++) {\n this.widgets[i + 1].value = controlValues[i]\n }\n }\n\n // When our value changes, update other widgets to reflect our changes\n // e.g. so LoadImage shows correct image\n widget.callback = useChainCallback(widget.callback, () => {\n this.applyToGraph()\n })\n\n // Use the biggest dimensions in case the widgets caused the node to grow\n this.setSize([\n Math.max(this.size[0], oldWidth),\n Math.max(this.size[1], oldHeight)\n ])\n\n if (!recreating) {\n // Grow our node more if required\n const sz = this.computeSize()\n if (this.size[0] < sz[0]) {\n this.size[0] = sz[0]\n }\n if (this.size[1] < sz[1]) {\n this.size[1] = sz[1]\n }\n\n requestAnimationFrame(() => {\n this.onResize?.(this.size)\n })\n }\n }\n\n recreateWidget() {\n const values = this.widgets?.map((w) => w.value)\n this.#removeWidgets()\n this.#onFirstConnection(true)\n if (values?.length && this.widgets) {\n for (let i = 0; i < this.widgets.length; i++)\n this.widgets[i].value = values[i]\n }\n return this.widgets?.[0]\n }\n\n #mergeWidgetConfig() {\n // Merge widget configs if the node has multiple outputs\n const output = this.outputs[0]\n const links = output.links ?? []\n\n const hasConfig = !!output.widget?.[CONFIG]\n if (hasConfig) {\n delete output.widget?.[CONFIG]\n }\n\n if (links?.length < 2 && hasConfig) {\n // Copy the widget options from the source\n if (links.length) {\n this.recreateWidget()\n }\n\n return\n }\n const config1 = (output.widget?.[GET_CONFIG] as () => InputSpec)?.()\n if (!config1) return\n const isNumber = config1[0] === 'INT' || config1[0] === 'FLOAT'\n if (!isNumber || !this.graph) return\n\n for (const linkId of links) {\n const link = this.graph.links[linkId]\n if (!link) continue // Can be null when removing a node\n\n const theirNode = this.graph.getNodeById(link.target_id)\n if (!theirNode) continue\n const theirInput = theirNode.inputs[link.target_slot]\n\n // Call is valid connection so it can merge the configs when validating\n this.#isValidConnection(theirInput, hasConfig)\n }\n }\n\n #isValidConnection(input: INodeInputSlot, forceUpdate?: boolean) {\n // Only allow connections where the configs match\n const output = this.outputs?.[0]\n const config2 = (input.widget?.[GET_CONFIG] as () => InputSpec)?.()\n if (!config2) return false\n\n return !!mergeIfValid.call(\n this,\n output,\n config2,\n forceUpdate,\n this.recreateWidget\n )\n }\n\n #removeWidgets() {\n if (this.widgets) {\n // Allow widgets to cleanup\n for (const w of this.widgets) {\n if (w.onRemove) {\n w.onRemove()\n }\n }\n\n // Temporarily store the current values in case the node is being recreated\n // e.g. by group node conversion\n this.controlValues = []\n this.lastType = this.widgets[0]?.type\n for (let i = 1; i < this.widgets.length; i++) {\n this.controlValues.push(this.widgets[i].value)\n }\n setTimeout(() => {\n delete this.lastType\n delete this.controlValues\n }, 15)\n this.widgets.length = 0\n }\n }\n\n onLastDisconnect() {\n // We can't remove + re-add the output here as if you drag a link over the same link\n // it removes, then re-adds, causing it to break\n this.outputs[0].type = '*'\n this.outputs[0].name = 'connect to widget input'\n delete this.outputs[0].widget\n\n this.#removeWidgets()\n }\n}\n\nexport function getWidgetConfig(\n slot: INodeInputSlot | INodeOutputSlot\n): InputSpec {\n return (slot.widget?.[CONFIG] ??\n (slot.widget?.[GET_CONFIG] as () => InputSpec)?.() ?? [\n '*',\n {}\n ]) as InputSpec\n}\n\nfunction getConfig(this: LGraphNode, widgetName: string) {\n const { nodeData } = this.constructor\n return (\n nodeData?.input?.required?.[widgetName] ??\n nodeData?.input?.optional?.[widgetName]\n )\n}\n\n/**\n * Convert a widget to an input slot.\n * @deprecated Widget to socket conversion is no longer necessary, as they co-exist now.\n * @param node The node to convert the widget to an input slot for.\n * @param widget The widget to convert to an input slot.\n * @returns The input slot that was converted from the widget or undefined if the widget is not found.\n * @knipIgnoreUnusedButUsedByCustomNodes\n */\nexport function convertToInput(\n node: LGraphNode,\n widget: IBaseWidget\n): INodeInputSlot | undefined {\n console.warn(\n 'Please remove call to convertToInput. Widget to socket conversion is no longer necessary, as they co-exist now.'\n )\n return node.inputs.find((slot) => slot.widget?.name === widget.name)\n}\n\nfunction getWidgetType(config: InputSpec) {\n // Special handling for COMBO so we restrict links based on the entries\n let type = config[0]\n if (type instanceof Array) {\n type = 'COMBO'\n }\n return { type }\n}\n\nexport function setWidgetConfig(slot: INodeInputSlot, config?: InputSpec) {\n if (!slot.widget) return\n if (config) {\n slot.widget[GET_CONFIG] = () => config\n } else {\n delete slot.widget\n }\n\n if (!(slot instanceof NodeSlot)) return\n const graph = slot.node.graph\n if (!graph) return\n const link = graph.links[slot.link ?? -1]\n if (!link) return\n const originNode = graph.getNodeById(link.origin_id)\n if (!originNode || !isPrimitiveNode(originNode)) return\n if (config) {\n originNode.recreateWidget()\n } else if (!app.configuringGraph) {\n originNode.disconnectOutput(0)\n originNode.onLastDisconnect()\n }\n}\n\nexport function mergeIfValid(\n output: INodeOutputSlot | INodeInputSlot,\n config2: InputSpec,\n forceUpdate?: boolean,\n recreateWidget?: () => void,\n config1?: InputSpec\n): { customConfig: InputSpec[1] } {\n if (!config1) {\n config1 = getWidgetConfig(output)\n }\n\n const customSpec = mergeInputSpec(config1, config2)\n\n if (customSpec || forceUpdate) {\n if (customSpec) {\n // @ts-expect-error fixme ts strict error\n output.widget[CONFIG] = customSpec\n }\n\n // @ts-expect-error fixme ts strict error\n const widget = recreateWidget?.call(this)\n // When deleting a node this can be null\n if (widget) {\n // @ts-expect-error fixme ts strict error\n const min = widget.options.min\n // @ts-expect-error fixme ts strict error\n const max = widget.options.max\n // @ts-expect-error fixme ts strict error\n if (min != null && widget.value < min) widget.value = min\n // @ts-expect-error fixme ts strict error\n if (max != null && widget.value > max) widget.value = max\n // @ts-expect-error fixme ts strict error\n widget.callback(widget.value)\n }\n }\n\n return { customConfig: customSpec?.[1] ?? {} }\n}\n\napp.registerExtension({\n name: 'Comfy.WidgetInputs',\n async beforeRegisterNodeDef(nodeType, _nodeData, app) {\n // @ts-expect-error adding extra property\n nodeType.prototype.convertWidgetToInput = function (this: LGraphNode) {\n console.warn(\n 'Please remove call to convertWidgetToInput. Widget to socket conversion is no longer necessary, as they co-exist now.'\n )\n return false\n }\n\n nodeType.prototype.onGraphConfigured = useChainCallback(\n nodeType.prototype.onGraphConfigured,\n function (this: LGraphNode) {\n if (!this.inputs) return\n this.widgets ??= []\n\n for (const input of this.inputs) {\n if (input.widget) {\n const name = input.widget.name\n if (!input.widget[GET_CONFIG]) {\n input.widget[GET_CONFIG] = () => getConfig.call(this, name)\n }\n\n const w = this.widgets?.find((w) => w.name === name)\n if (!w) {\n this.removeInput(this.inputs.findIndex((i) => i === input))\n }\n }\n }\n }\n )\n\n nodeType.prototype.onConfigure = useChainCallback(\n nodeType.prototype.onConfigure,\n function (this: LGraphNode) {\n if (!app.configuringGraph && this.inputs) {\n // On copy + paste of nodes, ensure that widget configs are set up\n for (const input of this.inputs) {\n if (input.widget && !input.widget[GET_CONFIG]) {\n const name = input.widget.name\n input.widget[GET_CONFIG] = () => getConfig.call(this, name)\n }\n }\n }\n }\n )\n\n // Double click a widget input to automatically attach a primitive\n const origOnInputDblClick = nodeType.prototype.onInputDblClick\n nodeType.prototype.onInputDblClick = function (\n this: LGraphNode,\n ...[slot, ...args]: CallbackParams<typeof origOnInputDblClick>\n ) {\n const r = origOnInputDblClick?.apply(this, [slot, ...args])\n\n const input = this.inputs[slot]\n if (!input.widget) {\n // Not a widget input or already handled input\n if (\n !(input.type in ComfyWidgets) &&\n !(\n (\n input.widget?.[GET_CONFIG] as (() => InputSpec) | undefined\n )?.()?.[0] instanceof Array\n )\n ) {\n return r //also Not a ComfyWidgets input or combo (do nothing)\n }\n }\n\n // Create a primitive node\n const node = LiteGraph.createNode('PrimitiveNode')\n const graph = app.canvas.graph\n if (!node || !graph) return r\n\n graph?.add(node)\n\n // Calculate a position that won't directly overlap another node\n const pos: [number, number] = [\n this.pos[0] - node.size[0] - 30,\n this.pos[1]\n ]\n while (graph.getNodeOnPos(pos[0], pos[1], graph.nodes))\n pos[1] += LiteGraph.NODE_TITLE_HEIGHT\n\n node.pos = pos\n node.connect(0, this, slot)\n node.title = input.name\n\n return r\n }\n },\n registerCustomNodes() {\n LiteGraph.registerNodeType(\n 'PrimitiveNode',\n Object.assign(PrimitiveNode, {\n title: 'Primitive'\n })\n )\n PrimitiveNode.category = 'utils'\n }\n})\n","import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants'\nimport { t } from '@/i18n'\nimport { type NodeId } from '@/lib/litegraph/src/LGraphNode'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport {\n type ExecutableLGraphNode,\n type ExecutionId,\n LGraphNode,\n LiteGraph,\n SubgraphNode\n} from '@/lib/litegraph/src/litegraph'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport {\n type ComfyLink,\n type ComfyNode,\n type ComfyWorkflowJSON\n} from '@/platform/workflow/validation/schemas/workflowSchema'\nimport type { ComfyNodeDef } from '@/schemas/nodeDefSchema'\nimport { useDialogService } from '@/services/dialogService'\nimport { useExecutionStore } from '@/stores/executionStore'\nimport { useNodeDefStore } from '@/stores/nodeDefStore'\nimport { useWidgetStore } from '@/stores/widgetStore'\nimport { type ComfyExtension } from '@/types/comfy'\nimport { ExecutableGroupNodeChildDTO } from '@/utils/executableGroupNodeChildDTO'\nimport { GROUP } from '@/utils/executableGroupNodeDto'\nimport { deserialiseAndCreate, serialise } from '@/utils/vintageClipboard'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\nimport { ManageGroupDialog } from './groupNodeManage'\nimport { mergeIfValid } from './widgetInputs'\n\ntype GroupNodeWorkflowData = {\n external: ComfyLink[]\n links: ComfyLink[]\n nodes: ComfyNode[]\n}\n\nconst Workflow = {\n InUse: {\n Free: 0,\n Registered: 1,\n InWorkflow: 2\n },\n // @ts-expect-error fixme ts strict error\n isInUseGroupNode(name) {\n const id = `${PREFIX}${SEPARATOR}${name}`\n // Check if lready registered/in use in this workflow\n // @ts-expect-error fixme ts strict error\n if (app.rootGraph.extra?.groupNodes?.[name]) {\n if (app.rootGraph.nodes.find((n) => n.type === id)) {\n return Workflow.InUse.InWorkflow\n } else {\n return Workflow.InUse.Registered\n }\n }\n return Workflow.InUse.Free\n },\n storeGroupNode(name: string, data: GroupNodeWorkflowData) {\n let extra = app.rootGraph.extra\n if (!extra) app.rootGraph.extra = extra = {}\n let groupNodes = extra.groupNodes\n if (!groupNodes) extra.groupNodes = groupNodes = {}\n // @ts-expect-error fixme ts strict error\n groupNodes[name] = data\n }\n}\n\nclass GroupNodeBuilder {\n nodes: LGraphNode[]\n // @ts-expect-error fixme ts strict error\n nodeData: GroupNodeWorkflowData\n\n constructor(nodes: LGraphNode[]) {\n this.nodes = nodes\n }\n\n async build() {\n const name = await this.getName()\n if (!name) return\n\n // Sort the nodes so they are in execution order\n // this allows for widgets to be in the correct order when reconstructing\n this.sortNodes()\n\n this.nodeData = this.getNodeData()\n Workflow.storeGroupNode(name, this.nodeData)\n\n return { name, nodeData: this.nodeData }\n }\n\n async getName() {\n const name = await useDialogService().prompt({\n title: t('groupNode.create'),\n message: t('groupNode.enterName'),\n defaultValue: ''\n })\n if (!name) return\n const used = Workflow.isInUseGroupNode(name)\n switch (used) {\n case Workflow.InUse.InWorkflow:\n useToastStore().addAlert(\n 'An in use group node with this name already exists embedded in this workflow, please remove any instances or use a new name.'\n )\n return\n case Workflow.InUse.Registered:\n if (\n !confirm(\n 'A group node with this name already exists embedded in this workflow, are you sure you want to overwrite it?'\n )\n ) {\n return\n }\n break\n }\n return name\n }\n\n sortNodes() {\n // Gets the builders nodes in graph execution order\n const nodesInOrder = app.rootGraph.computeExecutionOrder(false)\n this.nodes = this.nodes\n .map((node) => ({ index: nodesInOrder.indexOf(node), node }))\n // @ts-expect-error id might be string\n .sort((a, b) => a.index - b.index || a.node.id - b.node.id)\n .map(({ node }) => node)\n }\n\n getNodeData() {\n // @ts-expect-error fixme ts strict error\n const storeLinkTypes = (config) => {\n // Store link types for dynamically typed nodes e.g. reroutes\n for (const link of config.links) {\n const origin = app.rootGraph.getNodeById(link[4])\n // @ts-expect-error fixme ts strict error\n const type = origin.outputs[link[1]].type\n link.push(type)\n }\n }\n\n // @ts-expect-error fixme ts strict error\n const storeExternalLinks = (config) => {\n // Store any external links to the group in the config so when rebuilding we add extra slots\n config.external = []\n for (let i = 0; i < this.nodes.length; i++) {\n const node = this.nodes[i]\n if (!node.outputs?.length) continue\n for (let slot = 0; slot < node.outputs.length; slot++) {\n let hasExternal = false\n const output = node.outputs[slot]\n let type = output.type\n if (!output.links?.length) continue\n for (const l of output.links) {\n const link = app.rootGraph.links[l]\n if (!link) continue\n if (type === '*') type = link.type\n\n if (!app.canvas.selected_nodes[link.target_id]) {\n hasExternal = true\n break\n }\n }\n if (hasExternal) {\n config.external.push([i, slot, type])\n }\n }\n }\n }\n\n // Use the built in copyToClipboard function to generate the node data we need\n try {\n // @ts-expect-error fixme ts strict error\n const serialised = serialise(this.nodes, app.canvas?.graph)\n const config = JSON.parse(serialised)\n\n storeLinkTypes(config)\n storeExternalLinks(config)\n\n return config\n } finally {\n }\n }\n}\n\nexport class GroupNodeConfig {\n name: string\n nodeData: any\n inputCount: number\n oldToNewOutputMap: {}\n newToOldOutputMap: {}\n oldToNewInputMap: {}\n oldToNewWidgetMap: {}\n newToOldWidgetMap: {}\n primitiveDefs: {}\n widgetToPrimitive: {}\n primitiveToWidget: {}\n nodeInputs: {}\n outputVisibility: any[]\n // @ts-expect-error fixme ts strict error\n nodeDef: ComfyNodeDef\n // @ts-expect-error fixme ts strict error\n inputs: any[]\n // @ts-expect-error fixme ts strict error\n linksFrom: {}\n // @ts-expect-error fixme ts strict error\n linksTo: {}\n // @ts-expect-error fixme ts strict error\n externalFrom: {}\n\n // @ts-expect-error fixme ts strict error\n constructor(name, nodeData) {\n this.name = name\n this.nodeData = nodeData\n this.getLinks()\n\n this.inputCount = 0\n this.oldToNewOutputMap = {}\n this.newToOldOutputMap = {}\n this.oldToNewInputMap = {}\n this.oldToNewWidgetMap = {}\n this.newToOldWidgetMap = {}\n this.primitiveDefs = {}\n this.widgetToPrimitive = {}\n this.primitiveToWidget = {}\n this.nodeInputs = {}\n this.outputVisibility = []\n }\n\n async registerType(source = PREFIX) {\n this.nodeDef = {\n output: [],\n output_name: [],\n output_is_list: [],\n // @ts-expect-error Unused, doesn't exist\n output_is_hidden: [],\n name: source + SEPARATOR + this.name,\n display_name: this.name,\n category: 'group nodes' + (SEPARATOR + source),\n input: { required: {} },\n description: `Group node combining ${this.nodeData.nodes\n // @ts-expect-error fixme ts strict error\n .map((n) => n.type)\n .join(', ')}`,\n python_module: 'custom_nodes.' + this.name,\n\n [GROUP]: this\n }\n\n this.inputs = []\n const seenInputs = {}\n const seenOutputs = {}\n for (let i = 0; i < this.nodeData.nodes.length; i++) {\n const node = this.nodeData.nodes[i]\n node.index = i\n this.processNode(node, seenInputs, seenOutputs)\n }\n\n for (const p of this.#convertedToProcess) {\n // @ts-expect-error fixme ts strict error\n p()\n }\n // @ts-expect-error fixme ts strict error\n this.#convertedToProcess = null\n await app.registerNodeDef(`${PREFIX}${SEPARATOR}` + this.name, this.nodeDef)\n useNodeDefStore().addNodeDef(this.nodeDef)\n }\n\n getLinks() {\n this.linksFrom = {}\n this.linksTo = {}\n this.externalFrom = {}\n\n // Extract links for easy lookup\n for (const l of this.nodeData.links) {\n const [sourceNodeId, sourceNodeSlot, targetNodeId, targetNodeSlot] = l\n\n // Skip links outside the copy config\n if (sourceNodeId == null) continue\n\n // @ts-expect-error fixme ts strict error\n if (!this.linksFrom[sourceNodeId]) {\n // @ts-expect-error fixme ts strict error\n this.linksFrom[sourceNodeId] = {}\n }\n // @ts-expect-error fixme ts strict error\n if (!this.linksFrom[sourceNodeId][sourceNodeSlot]) {\n // @ts-expect-error fixme ts strict error\n this.linksFrom[sourceNodeId][sourceNodeSlot] = []\n }\n // @ts-expect-error fixme ts strict error\n this.linksFrom[sourceNodeId][sourceNodeSlot].push(l)\n\n // @ts-expect-error fixme ts strict error\n if (!this.linksTo[targetNodeId]) {\n // @ts-expect-error fixme ts strict error\n this.linksTo[targetNodeId] = {}\n }\n // @ts-expect-error fixme ts strict error\n this.linksTo[targetNodeId][targetNodeSlot] = l\n }\n\n if (this.nodeData.external) {\n for (const ext of this.nodeData.external) {\n // @ts-expect-error fixme ts strict error\n if (!this.externalFrom[ext[0]]) {\n // @ts-expect-error fixme ts strict error\n this.externalFrom[ext[0]] = { [ext[1]]: ext[2] }\n } else {\n // @ts-expect-error fixme ts strict error\n this.externalFrom[ext[0]][ext[1]] = ext[2]\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n processNode(node, seenInputs, seenOutputs) {\n const def = this.getNodeDef(node)\n if (!def) return\n\n const inputs = { ...def.input?.required, ...def.input?.optional }\n\n this.inputs.push(this.processNodeInputs(node, seenInputs, inputs))\n if (def.output?.length) this.processNodeOutputs(node, seenOutputs, def)\n }\n\n // @ts-expect-error fixme ts strict error\n getNodeDef(node) {\n // @ts-expect-error fixme ts strict error\n const def = globalDefs[node.type]\n if (def) return def\n\n // @ts-expect-error fixme ts strict error\n const linksFrom = this.linksFrom[node.index]\n if (node.type === 'PrimitiveNode') {\n // Skip as its not linked\n if (!linksFrom) return\n\n let type = linksFrom['0'][0][5]\n if (type === 'COMBO') {\n // Use the array items\n const source = node.outputs[0].widget.name\n const fromTypeName = this.nodeData.nodes[linksFrom['0'][0][2]].type\n // @ts-expect-error fixme ts strict error\n const fromType = globalDefs[fromTypeName]\n const input =\n fromType.input.required[source] ?? fromType.input.optional[source]\n type = input[0]\n }\n\n // @ts-expect-error fixme ts strict error\n const def = (this.primitiveDefs[node.index] = {\n input: {\n required: {\n value: [type, {}]\n }\n },\n output: [type],\n output_name: [],\n output_is_list: []\n })\n return def\n } else if (node.type === 'Reroute') {\n // @ts-expect-error fixme ts strict error\n const linksTo = this.linksTo[node.index]\n // @ts-expect-error fixme ts strict error\n if (linksTo && linksFrom && !this.externalFrom[node.index]?.[0]) {\n // Being used internally\n return null\n }\n\n let config = {}\n let rerouteType = '*'\n if (linksFrom) {\n for (const [, , id, slot] of linksFrom['0']) {\n const node = this.nodeData.nodes[id]\n const input = node.inputs[slot]\n if (rerouteType === '*') {\n rerouteType = input.type\n }\n if (input.widget) {\n // @ts-expect-error fixme ts strict error\n const targetDef = globalDefs[node.type]\n const targetWidget =\n targetDef.input.required[input.widget.name] ??\n targetDef.input.optional[input.widget.name]\n\n const widget = [targetWidget[0], config]\n const res = mergeIfValid(\n {\n // @ts-expect-error fixme ts strict error\n widget\n },\n targetWidget,\n false,\n null,\n widget\n )\n config = res?.customConfig ?? config\n }\n }\n } else if (linksTo) {\n const [id, slot] = linksTo['0']\n rerouteType = this.nodeData.nodes[id].outputs[slot].type\n } else {\n // Reroute used as a pipe\n for (const l of this.nodeData.links) {\n if (l[2] === node.index) {\n rerouteType = l[5]\n break\n }\n }\n if (rerouteType === '*') {\n // Check for an external link\n // @ts-expect-error fixme ts strict error\n const t = this.externalFrom[node.index]?.[0]\n if (t) {\n rerouteType = t\n }\n }\n }\n\n // @ts-expect-error\n config.forceInput = true\n return {\n input: {\n required: {\n [rerouteType]: [rerouteType, config]\n }\n },\n output: [rerouteType],\n output_name: [],\n output_is_list: []\n }\n }\n\n console.warn(\n 'Skipping virtual node ' +\n node.type +\n ' when building group node ' +\n this.name\n )\n }\n\n // @ts-expect-error fixme ts strict error\n getInputConfig(node, inputName, seenInputs, config, extra?) {\n const customConfig = this.nodeData.config?.[node.index]?.input?.[inputName]\n let name =\n customConfig?.name ??\n // @ts-expect-error fixme ts strict error\n node.inputs?.find((inp) => inp.name === inputName)?.label ??\n inputName\n let key = name\n let prefix = ''\n // Special handling for primitive to include the title if it is set rather than just \"value\"\n if ((node.type === 'PrimitiveNode' && node.title) || name in seenInputs) {\n prefix = `${node.title ?? node.type} `\n key = name = `${prefix}${inputName}`\n if (name in seenInputs) {\n name = `${prefix}${seenInputs[name]} ${inputName}`\n }\n }\n seenInputs[key] = (seenInputs[key] ?? 1) + 1\n\n if (inputName === 'seed' || inputName === 'noise_seed') {\n if (!extra) extra = {}\n extra.control_after_generate = `${prefix}control_after_generate`\n }\n if (config[0] === 'IMAGEUPLOAD') {\n if (!extra) extra = {}\n extra.widget =\n // @ts-expect-error fixme ts strict error\n this.oldToNewWidgetMap[node.index]?.[config[1]?.widget ?? 'image'] ??\n 'image'\n }\n\n if (extra) {\n config = [config[0], { ...config[1], ...extra }]\n }\n\n return { name, config, customConfig }\n }\n\n // @ts-expect-error fixme ts strict error\n processWidgetInputs(inputs, node, inputNames, seenInputs) {\n const slots = []\n const converted = new Map()\n // @ts-expect-error fixme ts strict error\n const widgetMap = (this.oldToNewWidgetMap[node.index] = {})\n for (const inputName of inputNames) {\n if (useWidgetStore().inputIsWidget(inputs[inputName])) {\n const convertedIndex = node.inputs?.findIndex(\n // @ts-expect-error fixme ts strict error\n (inp) => inp.name === inputName && inp.widget?.name === inputName\n )\n if (convertedIndex > -1) {\n // This widget has been converted to a widget\n // We need to store this in the correct position so link ids line up\n converted.set(convertedIndex, inputName)\n // @ts-expect-error fixme ts strict error\n widgetMap[inputName] = null\n } else {\n // Normal widget\n const { name, config } = this.getInputConfig(\n node,\n inputName,\n seenInputs,\n inputs[inputName]\n )\n // @ts-expect-error fixme ts strict error\n this.nodeDef.input.required[name] = config\n // @ts-expect-error fixme ts strict error\n widgetMap[inputName] = name\n // @ts-expect-error fixme ts strict error\n this.newToOldWidgetMap[name] = { node, inputName }\n }\n } else {\n // Normal input\n slots.push(inputName)\n }\n }\n return { converted, slots }\n }\n\n // @ts-expect-error fixme ts strict error\n checkPrimitiveConnection(link, inputName, inputs) {\n const sourceNode = this.nodeData.nodes[link[0]]\n if (sourceNode.type === 'PrimitiveNode') {\n // Merge link configurations\n const [sourceNodeId, _, targetNodeId, __] = link\n // @ts-expect-error fixme ts strict error\n const primitiveDef = this.primitiveDefs[sourceNodeId]\n const targetWidget = inputs[inputName]\n const primitiveConfig = primitiveDef.input.required.value\n const output = { widget: primitiveConfig }\n const config = mergeIfValid(\n // @ts-expect-error invalid slot type\n output,\n targetWidget,\n false,\n null,\n primitiveConfig\n )\n primitiveConfig[1] =\n (config?.customConfig ?? inputs[inputName][1])\n ? { ...inputs[inputName][1] }\n : {}\n\n // @ts-expect-error fixme ts strict error\n let name = this.oldToNewWidgetMap[sourceNodeId]['value']\n name = name.substr(0, name.length - 6)\n primitiveConfig[1].control_after_generate = true\n primitiveConfig[1].control_prefix = name\n\n // @ts-expect-error fixme ts strict error\n let toPrimitive = this.widgetToPrimitive[targetNodeId]\n if (!toPrimitive) {\n // @ts-expect-error fixme ts strict error\n toPrimitive = this.widgetToPrimitive[targetNodeId] = {}\n }\n if (toPrimitive[inputName]) {\n toPrimitive[inputName].push(sourceNodeId)\n }\n toPrimitive[inputName] = sourceNodeId\n\n // @ts-expect-error fixme ts strict error\n let toWidget = this.primitiveToWidget[sourceNodeId]\n if (!toWidget) {\n // @ts-expect-error fixme ts strict error\n toWidget = this.primitiveToWidget[sourceNodeId] = []\n }\n toWidget.push({ nodeId: targetNodeId, inputName })\n }\n }\n\n // @ts-expect-error fixme ts strict error\n processInputSlots(inputs, node, slots, linksTo, inputMap, seenInputs) {\n // @ts-expect-error fixme ts strict error\n this.nodeInputs[node.index] = {}\n for (let i = 0; i < slots.length; i++) {\n const inputName = slots[i]\n if (linksTo[i]) {\n this.checkPrimitiveConnection(linksTo[i], inputName, inputs)\n // This input is linked so we can skip it\n continue\n }\n\n const { name, config, customConfig } = this.getInputConfig(\n node,\n inputName,\n seenInputs,\n inputs[inputName]\n )\n\n // @ts-expect-error fixme ts strict error\n this.nodeInputs[node.index][inputName] = name\n if (customConfig?.visible === false) continue\n\n // @ts-expect-error fixme ts strict error\n this.nodeDef.input.required[name] = config\n inputMap[i] = this.inputCount++\n }\n }\n\n processConvertedWidgets(\n // @ts-expect-error fixme ts strict error\n inputs,\n // @ts-expect-error fixme ts strict error\n node,\n // @ts-expect-error fixme ts strict error\n slots,\n // @ts-expect-error fixme ts strict error\n converted,\n // @ts-expect-error fixme ts strict error\n linksTo,\n // @ts-expect-error fixme ts strict error\n inputMap,\n // @ts-expect-error fixme ts strict error\n seenInputs\n ) {\n // Add converted widgets sorted into their index order (ordered as they were converted) so link ids match up\n const convertedSlots = [...converted.keys()]\n .sort()\n .map((k) => converted.get(k))\n for (let i = 0; i < convertedSlots.length; i++) {\n const inputName = convertedSlots[i]\n if (linksTo[slots.length + i]) {\n this.checkPrimitiveConnection(\n linksTo[slots.length + i],\n inputName,\n inputs\n )\n // This input is linked so we can skip it\n continue\n }\n\n const { name, config } = this.getInputConfig(\n node,\n inputName,\n seenInputs,\n inputs[inputName],\n {\n defaultInput: true\n }\n )\n\n // @ts-expect-error fixme ts strict error\n this.nodeDef.input.required[name] = config\n // @ts-expect-error fixme ts strict error\n this.newToOldWidgetMap[name] = { node, inputName }\n\n // @ts-expect-error fixme ts strict error\n if (!this.oldToNewWidgetMap[node.index]) {\n // @ts-expect-error fixme ts strict error\n this.oldToNewWidgetMap[node.index] = {}\n }\n // @ts-expect-error fixme ts strict error\n this.oldToNewWidgetMap[node.index][inputName] = name\n\n inputMap[slots.length + i] = this.inputCount++\n }\n }\n\n #convertedToProcess = []\n // @ts-expect-error fixme ts strict error\n processNodeInputs(node, seenInputs, inputs) {\n // @ts-expect-error fixme ts strict error\n const inputMapping = []\n\n const inputNames = Object.keys(inputs)\n if (!inputNames.length) return\n\n const { converted, slots } = this.processWidgetInputs(\n inputs,\n node,\n inputNames,\n seenInputs\n )\n // @ts-expect-error fixme ts strict error\n const linksTo = this.linksTo[node.index] ?? {}\n // @ts-expect-error fixme ts strict error\n const inputMap = (this.oldToNewInputMap[node.index] = {})\n this.processInputSlots(inputs, node, slots, linksTo, inputMap, seenInputs)\n\n // Converted inputs have to be processed after all other nodes as they'll be at the end of the list\n // @ts-expect-error fixme ts strict error\n this.#convertedToProcess.push(() =>\n this.processConvertedWidgets(\n inputs,\n node,\n slots,\n converted,\n linksTo,\n inputMap,\n seenInputs\n )\n )\n\n // @ts-expect-error fixme ts strict error\n return inputMapping\n }\n\n // @ts-expect-error fixme ts strict error\n processNodeOutputs(node, seenOutputs, def) {\n // @ts-expect-error fixme ts strict error\n const oldToNew = (this.oldToNewOutputMap[node.index] = {})\n\n // Add outputs\n for (let outputId = 0; outputId < def.output.length; outputId++) {\n // @ts-expect-error fixme ts strict error\n const linksFrom = this.linksFrom[node.index]\n // If this output is linked internally we flag it to hide\n const hasLink =\n // @ts-expect-error fixme ts strict error\n linksFrom?.[outputId] && !this.externalFrom[node.index]?.[outputId]\n const customConfig =\n this.nodeData.config?.[node.index]?.output?.[outputId]\n const visible = customConfig?.visible ?? !hasLink\n this.outputVisibility.push(visible)\n if (!visible) {\n continue\n }\n\n // @ts-expect-error fixme ts strict error\n oldToNew[outputId] = this.nodeDef.output.length\n // @ts-expect-error fixme ts strict error\n this.newToOldOutputMap[this.nodeDef.output.length] = {\n node,\n slot: outputId\n }\n // @ts-expect-error fixme ts strict error\n this.nodeDef.output.push(def.output[outputId])\n // @ts-expect-error fixme ts strict error\n this.nodeDef.output_is_list.push(def.output_is_list[outputId])\n\n let label = customConfig?.name\n if (!label) {\n label = def.output_name?.[outputId] ?? def.output[outputId]\n // @ts-expect-error fixme ts strict error\n const output = node.outputs.find((o) => o.name === label)\n if (output?.label) {\n label = output.label\n }\n }\n\n let name = label\n if (name in seenOutputs) {\n const prefix = `${node.title ?? node.type} `\n name = `${prefix}${label}`\n if (name in seenOutputs) {\n name = `${prefix}${node.index} ${label}`\n }\n }\n seenOutputs[name] = 1\n\n // @ts-expect-error fixme ts strict error\n this.nodeDef.output_name.push(name)\n }\n }\n\n // @ts-expect-error fixme ts strict error\n static async registerFromWorkflow(groupNodes, missingNodeTypes) {\n for (const g in groupNodes) {\n const groupData = groupNodes[g]\n\n let hasMissing = false\n for (const n of groupData.nodes) {\n // Find missing node types\n if (!(n.type in LiteGraph.registered_node_types)) {\n missingNodeTypes.push({\n type: n.type,\n hint: ` (In group node '${PREFIX}${SEPARATOR}${g}')`\n })\n\n missingNodeTypes.push({\n type: `${PREFIX}${SEPARATOR}` + g,\n action: {\n text: 'Remove from workflow',\n // @ts-expect-error fixme ts strict error\n callback: (e) => {\n delete groupNodes[g]\n e.target.textContent = 'Removed'\n e.target.style.pointerEvents = 'none'\n e.target.style.opacity = 0.7\n }\n }\n })\n\n hasMissing = true\n }\n }\n\n if (hasMissing) continue\n\n const config = new GroupNodeConfig(g, groupData)\n await config.registerType()\n }\n }\n}\n\nexport class GroupNodeHandler {\n node: LGraphNode\n groupData: any\n innerNodes: any\n\n constructor(node: LGraphNode) {\n this.node = node\n this.groupData = node.constructor?.nodeData?.[GROUP]\n\n this.node.setInnerNodes = (innerNodes) => {\n this.innerNodes = innerNodes\n\n for (\n let innerNodeIndex = 0;\n innerNodeIndex < this.innerNodes.length;\n innerNodeIndex++\n ) {\n const innerNode = this.innerNodes[innerNodeIndex]\n innerNode.graph ??= this.node.graph\n\n for (const w of innerNode.widgets ?? []) {\n if (w.type === 'converted-widget') {\n w.serializeValue = w.origSerializeValue\n }\n }\n\n innerNode.index = innerNodeIndex\n // @ts-expect-error fixme ts strict error\n innerNode.getInputNode = (slot) => {\n // Check if this input is internal or external\n const externalSlot =\n this.groupData.oldToNewInputMap[innerNode.index]?.[slot]\n if (externalSlot != null) {\n return this.node.getInputNode(externalSlot)\n }\n\n // Internal link\n const innerLink = this.groupData.linksTo[innerNode.index]?.[slot]\n if (!innerLink) return null\n\n const inputNode = innerNodes[innerLink[0]]\n // Primitives will already apply their values\n if (inputNode.type === 'PrimitiveNode') return null\n\n return inputNode\n }\n\n // @ts-expect-error fixme ts strict error\n innerNode.getInputLink = (slot) => {\n const externalSlot =\n this.groupData.oldToNewInputMap[innerNode.index]?.[slot]\n if (externalSlot != null) {\n // The inner node is connected via the group node inputs\n const linkId = this.node.inputs[externalSlot].link\n // @ts-expect-error fixme ts strict error\n let link = app.rootGraph.links[linkId]\n\n // Use the outer link, but update the target to the inner node\n link = {\n ...link,\n target_id: innerNode.id,\n target_slot: +slot\n }\n return link\n }\n\n let link = this.groupData.linksTo[innerNode.index]?.[slot]\n if (!link) return null\n // Use the inner link, but update the origin node to be inner node id\n link = {\n origin_id: innerNodes[link[0]].id,\n origin_slot: link[1],\n target_id: innerNode.id,\n target_slot: +slot\n }\n return link\n }\n }\n }\n\n this.node.updateLink = (link) => {\n // Replace the group node reference with the internal node\n // @ts-expect-error Can this be removed? Or replaced with: LLink.create(link.asSerialisable())\n link = { ...link }\n const output = this.groupData.newToOldOutputMap[link.origin_slot]\n let innerNode = this.innerNodes[output.node.index]\n let l\n while (innerNode?.type === 'Reroute') {\n l = innerNode.getInputLink(0)\n innerNode = innerNode.getInputNode(0)\n }\n\n if (!innerNode) {\n return null\n }\n\n if (l && GroupNodeHandler.isGroupNode(innerNode)) {\n return innerNode.updateLink(l)\n }\n\n link.origin_id = innerNode.id\n link.origin_slot = l?.origin_slot ?? output.slot\n return link\n }\n\n /** @internal Used to flatten the subgraph before execution. Recursive; call with no args. */\n this.node.getInnerNodes = (\n computedNodeDtos: Map<ExecutionId, ExecutableLGraphNode>,\n /** The path of subgraph node IDs. */\n subgraphNodePath: readonly NodeId[] = [],\n /** The list of nodes to add to. */\n nodes: ExecutableLGraphNode[] = [],\n /** The set of visited nodes. */\n visited = new Set<LGraphNode>()\n ): ExecutableLGraphNode[] => {\n if (visited.has(this.node))\n throw new Error('RecursionError: while flattening subgraph')\n visited.add(this.node)\n\n if (!this.innerNodes) {\n // @ts-expect-error fixme ts strict error\n this.node.setInnerNodes(\n // @ts-expect-error fixme ts strict error\n this.groupData.nodeData.nodes.map((n, i) => {\n const innerNode = LiteGraph.createNode(n.type)\n // @ts-expect-error fixme ts strict error\n innerNode.configure(n)\n // @ts-expect-error fixme ts strict error\n innerNode.id = `${this.node.id}:${i}`\n // @ts-expect-error fixme ts strict error\n innerNode.graph = this.node.graph\n return innerNode\n })\n )\n }\n\n this.updateInnerWidgets()\n\n const subgraphInstanceIdPath = [...subgraphNodePath, this.node.id]\n\n // Assertion: Deprecated, does not matter.\n const subgraphNode = (this.node.graph?.getNodeById(\n subgraphNodePath.at(-1)\n ) ?? undefined) as SubgraphNode | undefined\n\n for (const node of this.innerNodes) {\n node.graph ??= this.node.graph\n\n // Create minimal DTOs rather than cloning the node\n const currentId = String(node.id)\n node.id = currentId.split(':').at(-1)\n const aVeryRealNode = new ExecutableGroupNodeChildDTO(\n node,\n subgraphInstanceIdPath,\n computedNodeDtos,\n subgraphNode\n )\n node.id = currentId\n aVeryRealNode.groupNodeHandler = this\n\n nodes.push(aVeryRealNode)\n }\n return nodes\n }\n\n // @ts-expect-error fixme ts strict error\n this.node.recreate = async () => {\n const id = this.node.id\n const sz = this.node.size\n // @ts-expect-error fixme ts strict error\n const nodes = this.node.convertToNodes()\n\n const groupNode = LiteGraph.createNode(this.node.type)\n // @ts-expect-error fixme ts strict error\n groupNode.id = id\n\n // Reuse the existing nodes for this instance\n // @ts-expect-error fixme ts strict error\n groupNode.setInnerNodes(nodes)\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].populateWidgets()\n // @ts-expect-error fixme ts strict error\n app.rootGraph.add(groupNode)\n // @ts-expect-error fixme ts strict error\n groupNode.setSize([\n // @ts-expect-error fixme ts strict error\n Math.max(groupNode.size[0], sz[0]),\n // @ts-expect-error fixme ts strict error\n Math.max(groupNode.size[1], sz[1])\n ])\n\n // Remove all converted nodes and relink them\n const builder = new GroupNodeBuilder(nodes)\n const nodeData = builder.getNodeData()\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].groupData.nodeData.links = nodeData.links\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].replaceNodes(nodes)\n return groupNode\n }\n\n // @ts-expect-error fixme ts strict error\n this.node.convertToNodes = () => {\n const addInnerNodes = () => {\n // Clone the node data so we dont mutate it for other nodes\n const c = { ...this.groupData.nodeData }\n c.nodes = [...c.nodes]\n // @ts-expect-error fixme ts strict error\n const innerNodes = this.node.getInnerNodes()\n let ids = []\n for (let i = 0; i < c.nodes.length; i++) {\n let id = innerNodes?.[i]?.id\n // Use existing IDs if they are set on the inner nodes\n // @ts-expect-error id can be string or number\n if (id == null || isNaN(id)) {\n // @ts-expect-error fixme ts strict error\n id = undefined\n } else {\n ids.push(id)\n }\n c.nodes[i] = { ...c.nodes[i], id }\n }\n deserialiseAndCreate(JSON.stringify(c), app.canvas)\n\n const [x, y] = this.node.pos\n let top\n let left\n // Configure nodes with current widget data\n const selectedIds = ids.length\n ? ids\n : Object.keys(app.canvas.selected_nodes)\n const newNodes = []\n for (let i = 0; i < selectedIds.length; i++) {\n const id = selectedIds[i]\n const newNode = app.rootGraph.getNodeById(id)\n const innerNode = innerNodes[i]\n newNodes.push(newNode)\n\n // @ts-expect-error fixme ts strict error\n if (left == null || newNode.pos[0] < left) {\n // @ts-expect-error fixme ts strict error\n left = newNode.pos[0]\n }\n // @ts-expect-error fixme ts strict error\n if (top == null || newNode.pos[1] < top) {\n // @ts-expect-error fixme ts strict error\n top = newNode.pos[1]\n }\n\n // @ts-expect-error fixme ts strict error\n if (!newNode.widgets) continue\n\n // @ts-expect-error fixme ts strict error\n const map = this.groupData.oldToNewWidgetMap[innerNode.index]\n if (map) {\n const widgets = Object.keys(map)\n\n for (const oldName of widgets) {\n const newName = map[oldName]\n if (!newName) continue\n\n // @ts-expect-error fixme ts strict error\n const widgetIndex = this.node.widgets.findIndex(\n (w) => w.name === newName\n )\n if (widgetIndex === -1) continue\n\n // Populate the main and any linked widgets\n if (innerNode.type === 'PrimitiveNode') {\n // @ts-expect-error fixme ts strict error\n for (let i = 0; i < newNode.widgets.length; i++) {\n // @ts-expect-error fixme ts strict error\n newNode.widgets[i].value =\n // @ts-expect-error fixme ts strict error\n this.node.widgets[widgetIndex + i].value\n }\n } else {\n // @ts-expect-error fixme ts strict error\n const outerWidget = this.node.widgets[widgetIndex]\n // @ts-expect-error fixme ts strict error\n const newWidget = newNode.widgets.find(\n (w) => w.name === oldName\n )\n if (!newWidget) continue\n\n newWidget.value = outerWidget.value\n // @ts-expect-error fixme ts strict error\n for (let w = 0; w < outerWidget.linkedWidgets?.length; w++) {\n // @ts-expect-error fixme ts strict error\n newWidget.linkedWidgets[w].value =\n // @ts-expect-error fixme ts strict error\n outerWidget.linkedWidgets[w].value\n }\n }\n }\n }\n }\n\n // Shift each node\n for (const newNode of newNodes) {\n // @ts-expect-error fixme ts strict error\n newNode.pos[0] -= left - x\n // @ts-expect-error fixme ts strict error\n newNode.pos[1] -= top - y\n }\n\n return { newNodes, selectedIds }\n }\n\n // @ts-expect-error fixme ts strict error\n const reconnectInputs = (selectedIds) => {\n for (const innerNodeIndex in this.groupData.oldToNewInputMap) {\n const id = selectedIds[innerNodeIndex]\n const newNode = app.rootGraph.getNodeById(id)\n const map = this.groupData.oldToNewInputMap[innerNodeIndex]\n for (const innerInputId in map) {\n const groupSlotId = map[innerInputId]\n if (groupSlotId == null) continue\n const slot = node.inputs[groupSlotId]\n if (slot.link == null) continue\n const link = app.rootGraph.links[slot.link]\n if (!link) continue\n // connect this node output to the input of another node\n const originNode = app.rootGraph.getNodeById(link.origin_id)\n // @ts-expect-error fixme ts strict error\n originNode.connect(link.origin_slot, newNode, +innerInputId)\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n const reconnectOutputs = (selectedIds) => {\n for (\n let groupOutputId = 0;\n groupOutputId < node.outputs?.length;\n groupOutputId++\n ) {\n const output = node.outputs[groupOutputId]\n if (!output.links) continue\n const links = [...output.links]\n for (const l of links) {\n const slot = this.groupData.newToOldOutputMap[groupOutputId]\n const link = app.rootGraph.links[l]\n const targetNode = app.rootGraph.getNodeById(link.target_id)\n const newNode = app.rootGraph.getNodeById(\n selectedIds[slot.node.index]\n )\n // @ts-expect-error fixme ts strict error\n newNode.connect(slot.slot, targetNode, link.target_slot)\n }\n }\n }\n\n app.canvas.emitBeforeChange()\n\n try {\n const { newNodes, selectedIds } = addInnerNodes()\n reconnectInputs(selectedIds)\n reconnectOutputs(selectedIds)\n app.rootGraph.remove(this.node)\n\n return newNodes\n } finally {\n app.canvas.emitAfterChange()\n }\n }\n\n const getExtraMenuOptions = this.node.getExtraMenuOptions\n // @ts-expect-error Should pass patched return value getExtraMenuOptions\n this.node.getExtraMenuOptions = function (_, options) {\n // @ts-expect-error fixme ts strict error\n getExtraMenuOptions?.apply(this, arguments)\n\n let optionIndex = options.findIndex((o) => o?.content === 'Outputs')\n if (optionIndex === -1) optionIndex = options.length\n else optionIndex++\n options.splice(\n optionIndex,\n 0,\n null,\n {\n content: 'Convert to nodes',\n // @ts-expect-error\n callback: () => {\n // @ts-expect-error fixme ts strict error\n return this.convertToNodes()\n }\n },\n {\n content: 'Manage Group Node',\n callback: () => manageGroupNodes(this.type)\n }\n )\n }\n\n // Draw custom collapse icon to identity this as a group\n const onDrawTitleBox = this.node.onDrawTitleBox\n this.node.onDrawTitleBox = function (ctx, height) {\n // @ts-expect-error fixme ts strict error\n onDrawTitleBox?.apply(this, arguments)\n\n const fill = ctx.fillStyle\n ctx.beginPath()\n ctx.rect(11, -height + 11, 2, 2)\n ctx.rect(14, -height + 11, 2, 2)\n ctx.rect(17, -height + 11, 2, 2)\n ctx.rect(11, -height + 14, 2, 2)\n ctx.rect(14, -height + 14, 2, 2)\n ctx.rect(17, -height + 14, 2, 2)\n ctx.rect(11, -height + 17, 2, 2)\n ctx.rect(14, -height + 17, 2, 2)\n ctx.rect(17, -height + 17, 2, 2)\n\n ctx.fillStyle = this.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR\n ctx.fill()\n ctx.fillStyle = fill\n }\n\n // Draw progress label\n const onDrawForeground = node.onDrawForeground\n const groupData = this.groupData.nodeData\n node.onDrawForeground = function (ctx) {\n // @ts-expect-error fixme ts strict error\n onDrawForeground?.apply?.(this, arguments)\n const progressState = useExecutionStore().nodeProgressStates[this.id]\n if (\n progressState &&\n progressState.state === 'running' &&\n this.runningInternalNodeId !== null\n ) {\n // @ts-expect-error fixme ts strict error\n const n = groupData.nodes[this.runningInternalNodeId]\n if (!n) return\n const message = `Running ${n.title || n.type} (${this.runningInternalNodeId}/${groupData.nodes.length})`\n ctx.save()\n ctx.font = '12px sans-serif'\n const sz = ctx.measureText(message)\n ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR\n ctx.beginPath()\n ctx.roundRect(\n 0,\n -LiteGraph.NODE_TITLE_HEIGHT - 20,\n sz.width + 12,\n 20,\n 5\n )\n ctx.fill()\n\n ctx.fillStyle = '#fff'\n ctx.fillText(message, 6, -LiteGraph.NODE_TITLE_HEIGHT - 6)\n ctx.restore()\n }\n }\n\n // Flag this node as needing to be reset\n const onExecutionStart = this.node.onExecutionStart\n this.node.onExecutionStart = function () {\n // @ts-expect-error fixme ts strict error\n this.resetExecution = true\n // @ts-expect-error fixme ts strict error\n return onExecutionStart?.apply(this, arguments)\n }\n\n const self = this\n const onNodeCreated = this.node.onNodeCreated\n this.node.onNodeCreated = function () {\n if (!this.widgets) {\n return\n }\n const config = self.groupData.nodeData.config\n if (config) {\n for (const n in config) {\n const inputs = config[n]?.input\n for (const w in inputs) {\n if (inputs[w].visible !== false) continue\n const widgetName = self.groupData.oldToNewWidgetMap[n][w]\n const widget = this.widgets.find((w) => w.name === widgetName)\n if (widget) {\n widget.type = 'hidden'\n widget.computeSize = () => [0, -4]\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n return onNodeCreated?.apply(this, arguments)\n }\n\n // @ts-expect-error fixme ts strict error\n function handleEvent(type, getId, getEvent) {\n // @ts-expect-error fixme ts strict error\n const handler = ({ detail }) => {\n const id = getId(detail)\n if (!id) return\n const node = app.rootGraph.getNodeById(id)\n if (node) return\n\n // @ts-expect-error fixme ts strict error\n const innerNodeIndex = this.innerNodes?.findIndex((n) => n.id == id)\n if (innerNodeIndex > -1) {\n // @ts-expect-error fixme ts strict error\n this.node.runningInternalNodeId = innerNodeIndex\n api.dispatchCustomEvent(\n type,\n // @ts-expect-error fixme ts strict error\n getEvent(detail, `${this.node.id}`, this.node)\n )\n }\n }\n api.addEventListener(type, handler)\n return handler\n }\n\n const executing = handleEvent.call(\n this,\n 'executing',\n // @ts-expect-error fixme ts strict error\n (d) => d,\n // @ts-expect-error fixme ts strict error\n (_, id) => id\n )\n\n const executed = handleEvent.call(\n this,\n 'executed',\n // @ts-expect-error fixme ts strict error\n (d) => d?.display_node || d?.node,\n // @ts-expect-error fixme ts strict error\n (d, id, node) => ({\n ...d,\n node: id,\n display_node: id,\n merge: !node.resetExecution\n })\n )\n\n const onRemoved = node.onRemoved\n this.node.onRemoved = function () {\n // @ts-expect-error fixme ts strict error\n onRemoved?.apply(this, arguments)\n // api.removeEventListener('progress_state', progress_state)\n api.removeEventListener('executing', executing)\n api.removeEventListener('executed', executed)\n }\n\n this.node.refreshComboInNode = (defs) => {\n // Update combo widget options\n for (const widgetName in this.groupData.newToOldWidgetMap) {\n // @ts-expect-error fixme ts strict error\n const widget = this.node.widgets.find((w) => w.name === widgetName)\n if (widget?.type === 'combo') {\n const old = this.groupData.newToOldWidgetMap[widgetName]\n const def = defs[old.node.type]\n const input =\n def?.input?.required?.[old.inputName] ??\n def?.input?.optional?.[old.inputName]\n if (!input) continue\n\n widget.options.values = input[0]\n\n if (\n old.inputName !== 'image' &&\n // @ts-expect-error Widget values\n !widget.options.values.includes(widget.value)\n ) {\n // @ts-expect-error fixme ts strict error\n widget.value = widget.options.values[0]\n // @ts-expect-error fixme ts strict error\n widget.callback(widget.value)\n }\n }\n }\n }\n }\n\n updateInnerWidgets() {\n for (const newWidgetName in this.groupData.newToOldWidgetMap) {\n // @ts-expect-error fixme ts strict error\n const newWidget = this.node.widgets.find((w) => w.name === newWidgetName)\n if (!newWidget) continue\n\n const newValue = newWidget.value\n const old = this.groupData.newToOldWidgetMap[newWidgetName]\n let innerNode = this.innerNodes[old.node.index]\n\n if (innerNode.type === 'PrimitiveNode') {\n innerNode.primitiveValue = newValue\n const primitiveLinked = this.groupData.primitiveToWidget[old.node.index]\n for (const linked of primitiveLinked ?? []) {\n const node = this.innerNodes[linked.nodeId]\n // @ts-expect-error fixme ts strict error\n const widget = node.widgets.find((w) => w.name === linked.inputName)\n\n if (widget) {\n widget.value = newValue\n }\n }\n continue\n } else if (innerNode.type === 'Reroute') {\n const rerouteLinks = this.groupData.linksFrom[old.node.index]\n if (rerouteLinks) {\n for (const [_, , targetNodeId, targetSlot] of rerouteLinks['0']) {\n const node = this.innerNodes[targetNodeId]\n const input = node.inputs[targetSlot]\n if (input.widget) {\n const widget = node.widgets?.find(\n // @ts-expect-error fixme ts strict error\n (w) => w.name === input.widget.name\n )\n if (widget) {\n widget.value = newValue\n }\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n const widget = innerNode.widgets?.find((w) => w.name === old.inputName)\n if (widget) {\n widget.value = newValue\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n populatePrimitive(_node, nodeId, oldName) {\n // Converted widget, populate primitive if linked\n const primitiveId = this.groupData.widgetToPrimitive[nodeId]?.[oldName]\n if (primitiveId == null) return\n const targetWidgetName =\n this.groupData.oldToNewWidgetMap[primitiveId]['value']\n // @ts-expect-error fixme ts strict error\n const targetWidgetIndex = this.node.widgets.findIndex(\n (w) => w.name === targetWidgetName\n )\n if (targetWidgetIndex > -1) {\n const primitiveNode = this.innerNodes[primitiveId]\n let len = primitiveNode.widgets.length\n if (\n len - 1 !==\n // @ts-expect-error fixme ts strict error\n this.node.widgets[targetWidgetIndex].linkedWidgets?.length\n ) {\n // Fallback handling for if some reason the primitive has a different number of widgets\n // we dont want to overwrite random widgets, better to leave blank\n len = 1\n }\n for (let i = 0; i < len; i++) {\n // @ts-expect-error fixme ts strict error\n this.node.widgets[targetWidgetIndex + i].value =\n primitiveNode.widgets[i].value\n }\n }\n return true\n }\n\n // @ts-expect-error fixme ts strict error\n populateReroute(node, nodeId, map) {\n if (node.type !== 'Reroute') return\n\n const link = this.groupData.linksFrom[nodeId]?.[0]?.[0]\n if (!link) return\n const [, , targetNodeId, targetNodeSlot] = link\n const targetNode = this.groupData.nodeData.nodes[targetNodeId]\n const inputs = targetNode.inputs\n const targetWidget = inputs?.[targetNodeSlot]?.widget\n if (!targetWidget) return\n\n const offset = inputs.length - (targetNode.widgets_values?.length ?? 0)\n const v = targetNode.widgets_values?.[targetNodeSlot - offset]\n if (v == null) return\n\n const widgetName = Object.values(map)[0]\n // @ts-expect-error fixme ts strict error\n const widget = this.node.widgets.find((w) => w.name === widgetName)\n if (widget) {\n widget.value = v\n }\n }\n\n populateWidgets() {\n if (!this.node.widgets) return\n\n for (\n let nodeId = 0;\n nodeId < this.groupData.nodeData.nodes.length;\n nodeId++\n ) {\n const node = this.groupData.nodeData.nodes[nodeId]\n const map = this.groupData.oldToNewWidgetMap[nodeId] ?? {}\n const widgets = Object.keys(map)\n\n if (!node.widgets_values?.length) {\n // special handling for populating values into reroutes\n // this allows primitives connect to them to pick up the correct value\n this.populateReroute(node, nodeId, map)\n continue\n }\n\n let linkedShift = 0\n for (let i = 0; i < widgets.length; i++) {\n const oldName = widgets[i]\n const newName = map[oldName]\n const widgetIndex = this.node.widgets.findIndex(\n (w) => w.name === newName\n )\n const mainWidget = this.node.widgets[widgetIndex]\n if (\n this.populatePrimitive(node, nodeId, oldName) ||\n widgetIndex === -1\n ) {\n // Find the inner widget and shift by the number of linked widgets as they will have been removed too\n const innerWidget = this.innerNodes[nodeId].widgets?.find(\n // @ts-expect-error fixme ts strict error\n (w) => w.name === oldName\n )\n linkedShift += innerWidget?.linkedWidgets?.length ?? 0\n }\n if (widgetIndex === -1) {\n continue\n }\n\n // Populate the main and any linked widget\n mainWidget.value = node.widgets_values[i + linkedShift]\n // @ts-expect-error fixme ts strict error\n for (let w = 0; w < mainWidget.linkedWidgets?.length; w++) {\n this.node.widgets[widgetIndex + w + 1].value =\n node.widgets_values[i + ++linkedShift]\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n replaceNodes(nodes) {\n let top\n let left\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]\n if (left == null || node.pos[0] < left) {\n left = node.pos[0]\n }\n if (top == null || node.pos[1] < top) {\n top = node.pos[1]\n }\n\n this.linkOutputs(node, i)\n app.rootGraph.remove(node)\n\n // Set internal ID to what is expected after workflow is reloaded\n node.id = `${this.node.id}:${i}`\n }\n\n this.linkInputs()\n this.node.pos = [left, top]\n }\n\n // @ts-expect-error fixme ts strict error\n linkOutputs(originalNode, nodeId) {\n if (!originalNode.outputs) return\n\n for (const output of originalNode.outputs) {\n if (!output.links) continue\n // Clone the links as they'll be changed if we reconnect\n const links = [...output.links]\n for (const l of links) {\n const link = app.rootGraph.links[l]\n if (!link) continue\n\n const targetNode = app.rootGraph.getNodeById(link.target_id)\n const newSlot =\n this.groupData.oldToNewOutputMap[nodeId]?.[link.origin_slot]\n if (newSlot != null) {\n // @ts-expect-error fixme ts strict error\n this.node.connect(newSlot, targetNode, link.target_slot)\n }\n }\n }\n }\n\n linkInputs() {\n for (const link of this.groupData.nodeData.links ?? []) {\n const [, originSlot, targetId, targetSlot, actualOriginId] = link\n const originNode = app.rootGraph.getNodeById(actualOriginId)\n if (!originNode) continue // this node is in the group\n originNode.connect(\n originSlot,\n // @ts-expect-error Valid - uses deprecated interface. Required check: if (graph.getNodeById(this.node.id) !== this.node) report()\n this.node.id,\n this.groupData.oldToNewInputMap[targetId][targetSlot]\n )\n }\n }\n\n // @ts-expect-error fixme ts strict error\n static getGroupData(node) {\n return (node.nodeData ?? node.constructor?.nodeData)?.[GROUP]\n }\n\n static isGroupNode(node: LGraphNode) {\n return !!node.constructor?.nodeData?.[GROUP]\n }\n\n static async fromNodes(nodes: LGraphNode[]) {\n // Process the nodes into the stored workflow group node data\n const builder = new GroupNodeBuilder(nodes)\n const res = await builder.build()\n if (!res) return\n\n const { name, nodeData } = res\n\n // Convert this data into a LG node definition and register it\n const config = new GroupNodeConfig(name, nodeData)\n await config.registerType()\n\n const groupNode = LiteGraph.createNode(`${PREFIX}${SEPARATOR}${name}`)\n // Reuse the existing nodes for this instance\n // @ts-expect-error fixme ts strict error\n groupNode.setInnerNodes(builder.nodes)\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].populateWidgets()\n // @ts-expect-error fixme ts strict error\n app.rootGraph.add(groupNode)\n\n // Remove all converted nodes and relink them\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].replaceNodes(builder.nodes)\n return groupNode\n }\n}\n\nconst replaceLegacySeparators = (nodes: ComfyNode[]): void => {\n for (const node of nodes) {\n if (typeof node.type === 'string' && node.type.startsWith('workflow/')) {\n node.type = node.type.replace(/^workflow\\//, `${PREFIX}${SEPARATOR}`)\n }\n }\n}\n\n/**\n * Convert selected nodes to a group node\n * @throws {Error} if no nodes are selected\n * @throws {Error} if a group node is already selected\n * @throws {Error} if a group node is selected\n *\n * The context menu item should not be available if any of the above conditions are met.\n * The error is automatically handled by the commandStore when the command is executed.\n */\nasync function convertSelectedNodesToGroupNode() {\n const nodes = Object.values(app.canvas.selected_nodes ?? {})\n if (nodes.length === 0) {\n throw new Error('No nodes selected')\n }\n if (nodes.length === 1) {\n throw new Error('Please select multiple nodes to convert to group node')\n }\n\n for (const node of nodes) {\n if (node instanceof SubgraphNode) {\n throw new Error('Selected nodes contain a subgraph node')\n }\n if (GroupNodeHandler.isGroupNode(node)) {\n throw new Error('Selected nodes contain a group node')\n }\n }\n return await GroupNodeHandler.fromNodes(nodes)\n}\n\nconst convertDisabled = (selected: LGraphNode[]) =>\n selected.length < 2 || !!selected.find((n) => GroupNodeHandler.isGroupNode(n))\n\nfunction ungroupSelectedGroupNodes() {\n const nodes = Object.values(app.canvas.selected_nodes ?? {})\n for (const node of nodes) {\n if (GroupNodeHandler.isGroupNode(node)) {\n node.convertToNodes?.()\n }\n }\n}\n\nfunction manageGroupNodes(type?: string) {\n new ManageGroupDialog(app).show(type)\n}\n\nconst id = 'Comfy.GroupNode'\n// @ts-expect-error fixme ts strict error\nlet globalDefs\nconst ext: ComfyExtension = {\n name: id,\n commands: [\n {\n id: 'Comfy.GroupNode.ConvertSelectedNodesToGroupNode',\n label: 'Convert selected nodes to group node',\n icon: 'pi pi-sitemap',\n versionAdded: '1.3.17',\n function: () => convertSelectedNodesToGroupNode()\n },\n {\n id: 'Comfy.GroupNode.UngroupSelectedGroupNodes',\n label: 'Ungroup selected group nodes',\n icon: 'pi pi-sitemap',\n versionAdded: '1.3.17',\n function: () => ungroupSelectedGroupNodes()\n },\n {\n id: 'Comfy.GroupNode.ManageGroupNodes',\n label: 'Manage group nodes',\n icon: 'pi pi-cog',\n versionAdded: '1.3.17',\n function: (...args: unknown[]) =>\n manageGroupNodes(args[0] as string | undefined)\n }\n ],\n keybindings: [\n {\n commandId: 'Comfy.GroupNode.ConvertSelectedNodesToGroupNode',\n combo: {\n alt: true,\n key: 'g'\n }\n },\n {\n commandId: 'Comfy.GroupNode.UngroupSelectedGroupNodes',\n combo: {\n alt: true,\n shift: true,\n key: 'G'\n }\n }\n ],\n\n getCanvasMenuItems(canvas): IContextMenuValue[] {\n const items: IContextMenuValue[] = []\n const selected = Object.values(canvas.selected_nodes ?? {})\n const convertEnabled = !convertDisabled(selected)\n\n items.push({\n content: `Convert to Group Node (Deprecated)`,\n disabled: !convertEnabled,\n // @ts-expect-error fixme ts strict error - async callback\n callback: () => convertSelectedNodesToGroupNode()\n })\n\n const groups = canvas.graph?.extra?.groupNodes\n const manageDisabled = !groups || !Object.keys(groups).length\n items.push({\n content: `Manage Group Nodes`,\n disabled: manageDisabled,\n callback: () => manageGroupNodes()\n })\n\n return items\n },\n\n getNodeMenuItems(node): IContextMenuValue[] {\n if (GroupNodeHandler.isGroupNode(node)) {\n return []\n }\n\n const selected = Object.values(app.canvas.selected_nodes ?? {})\n const convertEnabled = !convertDisabled(selected)\n\n return [\n {\n content: `Convert to Group Node (Deprecated)`,\n disabled: !convertEnabled,\n // @ts-expect-error fixme ts strict error - async callback\n callback: () => convertSelectedNodesToGroupNode()\n }\n ]\n },\n async beforeConfigureGraph(\n graphData: ComfyWorkflowJSON,\n missingNodeTypes: string[]\n ) {\n const nodes = graphData?.extra?.groupNodes\n if (nodes) {\n replaceLegacySeparators(graphData.nodes)\n await GroupNodeConfig.registerFromWorkflow(nodes, missingNodeTypes)\n }\n },\n addCustomNodeDefs(defs) {\n // Store this so we can mutate it later with group nodes\n globalDefs = defs\n },\n nodeCreated(node) {\n if (GroupNodeHandler.isGroupNode(node)) {\n // @ts-expect-error fixme ts strict error\n node[GROUP] = new GroupNodeHandler(node)\n\n // Ensure group nodes pasted from other workflows are stored\n // @ts-expect-error fixme ts strict error\n if (node.title && node[GROUP]?.groupData?.nodeData) {\n // @ts-expect-error fixme ts strict error\n Workflow.storeGroupNode(node.title, node[GROUP].groupData.nodeData)\n }\n }\n },\n // @ts-expect-error fixme ts strict error\n async refreshComboInNodes(defs) {\n // Re-register group nodes so new ones are created with the correct options\n // @ts-expect-error fixme ts strict error\n Object.assign(globalDefs, defs)\n const nodes = app.rootGraph.extra?.groupNodes\n if (nodes) {\n await GroupNodeConfig.registerFromWorkflow(nodes, {})\n }\n }\n}\n\napp.registerExtension(ext)\n","import type {\n IContextMenuValue,\n Positionable\n} from '@/lib/litegraph/src/interfaces'\nimport {\n LGraphCanvas,\n LGraphGroup,\n type LGraphNode\n} from '@/lib/litegraph/src/litegraph'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport type { ComfyExtension } from '@/types/comfy'\n\nimport { app } from '../../scripts/app'\n\nfunction setNodeMode(node: LGraphNode, mode: number) {\n node.mode = mode\n node.graph?.change()\n}\n\nfunction addNodesToGroup(group: LGraphGroup, items: Iterable<Positionable>) {\n const padding = useSettingStore().get('Comfy.GroupSelectedNodes.Padding')\n group.resizeTo([...group.children, ...items], padding)\n}\n\nconst ext: ComfyExtension = {\n name: 'Comfy.GroupOptions',\n\n getCanvasMenuItems(canvas: LGraphCanvas): IContextMenuValue[] {\n const items: IContextMenuValue[] = []\n\n // @ts-expect-error fixme ts strict error\n const group = canvas.graph.getGroupOnPos(\n canvas.graph_mouse[0],\n canvas.graph_mouse[1]\n )\n\n if (!group) {\n if (canvas.selectedItems.size > 0) {\n items.push({\n content: 'Add Group For Selected Nodes',\n callback: () => {\n const group = new LGraphGroup()\n addNodesToGroup(group, canvas.selectedItems)\n // @ts-expect-error fixme ts strict error\n canvas.graph.add(group)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n\n group.recomputeInsideNodes()\n }\n })\n }\n\n return items\n }\n\n // Group nodes aren't recomputed until the group is moved, this ensures the nodes are up-to-date\n group.recomputeInsideNodes()\n const nodesInGroup = group.nodes\n\n items.push({\n content: 'Add Selected Nodes To Group',\n disabled: !canvas.selectedItems?.size,\n callback: () => {\n addNodesToGroup(group, canvas.selectedItems)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n }\n })\n\n // No nodes in group, return default options\n if (nodesInGroup.length === 0) {\n return items\n } else {\n // Add a separator between the default options and the group options\n // @ts-expect-error fixme ts strict error\n items.push(null)\n }\n\n // Check if all nodes are the same mode\n let allNodesAreSameMode = true\n for (let i = 1; i < nodesInGroup.length; i++) {\n if (nodesInGroup[i].mode !== nodesInGroup[0].mode) {\n allNodesAreSameMode = false\n break\n }\n }\n\n items.push({\n content: 'Fit Group To Nodes',\n callback: () => {\n group.recomputeInsideNodes()\n const padding = useSettingStore().get(\n 'Comfy.GroupSelectedNodes.Padding'\n )\n group.resizeTo(group.children, padding)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n }\n })\n\n items.push({\n content: 'Select Nodes',\n callback: () => {\n canvas.selectNodes(nodesInGroup)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n canvas.canvas.focus()\n }\n })\n\n // Modes\n // 0: Always\n // 1: On Event\n // 2: Never\n // 3: On Trigger\n // 4: Bypass\n // If all nodes are the same mode, add a menu option to change the mode\n if (allNodesAreSameMode) {\n const mode = nodesInGroup[0].mode\n switch (mode) {\n case 0:\n // All nodes are always, option to disable, and bypass\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n break\n case 2:\n // All nodes are never, option to enable, and bypass\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n break\n case 4:\n // All nodes are bypass, option to enable, and disable\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n break\n default:\n // All nodes are On Trigger or On Event(Or other?), option to disable, set to always, or bypass\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n break\n }\n } else {\n // Nodes are not all the same mode, add a menu option to change the mode to always, never, or bypass\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n }\n\n return items\n }\n}\n\napp.registerExtension(ext)\n","import type { NodeExecutionOutput } from '@/schemas/apiSchema'\nimport { api } from '@/scripts/api'\nimport { app } from '@/scripts/app'\nimport { useExtensionService } from '@/services/extensionService'\n\nuseExtensionService().registerExtension({\n name: 'Comfy.ImageCompare',\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'ImageCompare') return\n\n const [oldWidth, oldHeight] = node.size\n node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 350)])\n\n const onExecuted = node.onExecuted\n\n node.onExecuted = function (output: NodeExecutionOutput) {\n onExecuted?.call(this, output)\n\n const aImages = (output as Record<string, unknown>).a_images as\n | Record<string, string>[]\n | undefined\n const bImages = (output as Record<string, unknown>).b_images as\n | Record<string, string>[]\n | undefined\n const rand = app.getRandParam()\n\n const beforeUrl =\n aImages && aImages.length > 0\n ? api.apiURL(`/view?${new URLSearchParams(aImages[0])}${rand}`)\n : ''\n const afterUrl =\n bImages && bImages.length > 0\n ? api.apiURL(`/view?${new URLSearchParams(bImages[0])}${rand}`)\n : ''\n\n const widget = node.widgets?.find((w) => w.type === 'imagecompare')\n\n if (widget) {\n widget.value = {\n before: beforeUrl,\n after: afterUrl\n }\n widget.callback?.(widget.value)\n }\n }\n }\n})\n","import { t } from '@/i18n'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport Load3d from '@/extensions/core/load3d/Load3d'\nimport { LiteGraph } from '@/lib/litegraph/src/litegraph'\n\nconst EXPORT_FORMATS = [\n { label: 'GLB', value: 'glb' },\n { label: 'OBJ', value: 'obj' },\n { label: 'STL', value: 'stl' }\n] as const\n\n/**\n * Creates export menu items for a 3D node using the new extension API.\n * Returns an array of context menu items including a separator and export submenu.\n */\nexport function createExportMenuItems(\n load3d: Load3d\n): (IContextMenuValue | null)[] {\n return [\n null, // Separator\n {\n content: 'Save',\n has_submenu: true,\n callback: (_value, _options, event, prev_menu) => {\n const submenuOptions: IContextMenuValue[] = EXPORT_FORMATS.map(\n (format) => ({\n content: format.label,\n callback: () => {\n void (async () => {\n try {\n await load3d.exportModel(format.value)\n useToastStore().add({\n severity: 'success',\n summary: t('toastMessages.exportSuccess', {\n format: format.label\n })\n })\n } catch (error) {\n console.error('Export failed:', error)\n useToastStore().addAlert(\n t('toastMessages.failedToExportModel', {\n format: format.label\n })\n )\n }\n })()\n }\n })\n )\n\n new LiteGraph.ContextMenu(submenuOptions, {\n event,\n parentMenu: prev_menu\n })\n }\n }\n ]\n}\n","import Load3d from '@/extensions/core/load3d/Load3d'\nimport Load3dUtils from '@/extensions/core/load3d/Load3dUtils'\nimport type {\n CameraConfig,\n CameraState,\n LightConfig,\n ModelConfig,\n SceneConfig\n} from '@/extensions/core/load3d/interfaces'\nimport type { Dictionary } from '@/lib/litegraph/src/interfaces'\nimport type { NodeProperty } from '@/lib/litegraph/src/LGraphNode'\nimport type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport { api } from '@/scripts/api'\n\ntype Load3DConfigurationSettings = {\n loadFolder: string\n modelWidget: IBaseWidget\n cameraState?: CameraState\n width?: IBaseWidget\n height?: IBaseWidget\n bgImagePath?: string\n}\n\nclass Load3DConfiguration {\n constructor(\n private load3d: Load3d,\n private properties?: Dictionary<NodeProperty | undefined>\n ) {}\n\n configureForSaveMesh(loadFolder: 'input' | 'output', filePath: string) {\n this.setupModelHandlingForSaveMesh(filePath, loadFolder)\n this.setupDefaultProperties()\n }\n\n configure(setting: Load3DConfigurationSettings) {\n this.setupModelHandling(\n setting.modelWidget,\n setting.loadFolder,\n setting.cameraState\n )\n this.setupTargetSize(setting.width, setting.height)\n this.setupDefaultProperties(setting.bgImagePath)\n }\n\n private setupTargetSize(width?: IBaseWidget, height?: IBaseWidget) {\n if (width && height) {\n this.load3d.setTargetSize(width.value as number, height.value as number)\n\n width.callback = (value: number) => {\n this.load3d.setTargetSize(value, height.value as number)\n }\n\n height.callback = (value: number) => {\n this.load3d.setTargetSize(width.value as number, value)\n }\n }\n }\n\n private setupModelHandlingForSaveMesh(filePath: string, loadFolder: string) {\n const onModelWidgetUpdate = this.createModelUpdateHandler(loadFolder)\n\n if (filePath) {\n onModelWidgetUpdate(filePath)\n }\n }\n\n private setupModelHandling(\n modelWidget: IBaseWidget,\n loadFolder: string,\n cameraState?: CameraState\n ) {\n const onModelWidgetUpdate = this.createModelUpdateHandler(\n loadFolder,\n cameraState\n )\n if (modelWidget.value) {\n onModelWidgetUpdate(modelWidget.value)\n }\n\n const originalCallback = modelWidget.callback\n\n let currentValue = modelWidget.value\n Object.defineProperty(modelWidget, 'value', {\n get() {\n return currentValue\n },\n set(newValue) {\n currentValue = newValue\n if (modelWidget.callback && newValue !== undefined && newValue !== '') {\n modelWidget.callback(newValue)\n }\n },\n enumerable: true,\n configurable: true\n })\n\n modelWidget.callback = (value: string | number | boolean | object) => {\n onModelWidgetUpdate(value)\n\n if (originalCallback) {\n originalCallback(value)\n }\n }\n }\n\n private setupDefaultProperties(bgImagePath?: string) {\n const sceneConfig = this.loadSceneConfig()\n this.applySceneConfig(sceneConfig, bgImagePath)\n\n const cameraConfig = this.loadCameraConfig()\n this.applyCameraConfig(cameraConfig)\n\n const lightConfig = this.loadLightConfig()\n this.applyLightConfig(lightConfig)\n }\n\n private loadSceneConfig(): SceneConfig {\n if (this.properties && 'Scene Config' in this.properties) {\n return this.properties['Scene Config'] as SceneConfig\n }\n\n return {\n showGrid: useSettingStore().get('Comfy.Load3D.ShowGrid'),\n backgroundColor:\n '#' + useSettingStore().get('Comfy.Load3D.BackgroundColor'),\n backgroundImage: ''\n } as SceneConfig\n }\n\n private loadCameraConfig(): CameraConfig {\n if (this.properties && 'Camera Config' in this.properties) {\n return this.properties['Camera Config'] as CameraConfig\n }\n\n return {\n cameraType: useSettingStore().get('Comfy.Load3D.CameraType'),\n fov: 35\n } as CameraConfig\n }\n\n private loadLightConfig(): LightConfig {\n if (this.properties && 'Light Config' in this.properties) {\n return this.properties['Light Config'] as LightConfig\n }\n\n return {\n intensity: useSettingStore().get('Comfy.Load3D.LightIntensity')\n } as LightConfig\n }\n\n private loadModelConfig(): ModelConfig {\n if (this.properties && 'Model Config' in this.properties) {\n return this.properties['Model Config'] as ModelConfig\n }\n\n return {\n upDirection: 'original',\n materialMode: 'original'\n } as ModelConfig\n }\n\n private applySceneConfig(config: SceneConfig, bgImagePath?: string) {\n this.load3d.toggleGrid(config.showGrid)\n this.load3d.setBackgroundColor(config.backgroundColor)\n if (config.backgroundImage) {\n if (bgImagePath && bgImagePath != config.backgroundImage) {\n return\n }\n\n void this.load3d.setBackgroundImage(config.backgroundImage)\n\n if (config.backgroundRenderMode) {\n this.load3d.setBackgroundRenderMode(config.backgroundRenderMode)\n }\n }\n }\n\n private applyCameraConfig(config: CameraConfig) {\n this.load3d.toggleCamera(config.cameraType)\n this.load3d.setFOV(config.fov)\n\n if (config.state) {\n this.load3d.setCameraState(config.state)\n }\n }\n\n private applyLightConfig(config: LightConfig) {\n this.load3d.setLightIntensity(config.intensity)\n }\n\n private applyModelConfig(config: ModelConfig) {\n this.load3d.setUpDirection(config.upDirection)\n this.load3d.setMaterialMode(config.materialMode)\n }\n\n private createModelUpdateHandler(\n loadFolder: string,\n cameraState?: CameraState\n ) {\n let isFirstLoad = true\n return async (value: string | number | boolean | object) => {\n if (!value) return\n\n const filename = value as string\n\n this.setResourceFolder(filename)\n\n const modelUrl = api.apiURL(\n Load3dUtils.getResourceURL(\n ...Load3dUtils.splitFilePath(filename),\n loadFolder\n )\n )\n\n await this.load3d.loadModel(modelUrl, filename)\n\n const modelConfig = this.loadModelConfig()\n this.applyModelConfig(modelConfig)\n\n if (isFirstLoad && cameraState) {\n try {\n this.load3d.setCameraState(cameraState)\n } catch (error) {\n console.warn('Failed to restore camera state:', error)\n }\n isFirstLoad = false\n }\n }\n }\n\n private setResourceFolder(filename: string): void {\n const pathParts = filename.split('/').filter((part) => part.trim())\n\n if (pathParts.length <= 2) {\n return\n }\n\n const subfolderParts = pathParts.slice(1, -1)\n const subfolder = subfolderParts.join('/')\n\n if (subfolder && this.properties) {\n this.properties['Resource Folder'] = subfolder\n }\n }\n}\n\nexport default Load3DConfiguration\n","import { nextTick } from 'vue'\n\nimport Load3D from '@/components/load3d/Load3D.vue'\nimport Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'\nimport { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d'\nimport { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'\nimport Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'\nimport Load3dUtils from '@/extensions/core/load3d/Load3dUtils'\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport type { IStringWidget } from '@/lib/litegraph/src/types/widgets'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport { api } from '@/scripts/api'\nimport { ComfyApp, app } from '@/scripts/app'\nimport { ComponentWidgetImpl, addWidget } from '@/scripts/domWidget'\nimport { useExtensionService } from '@/services/extensionService'\nimport { useLoad3dService } from '@/services/load3dService'\nimport { useDialogStore } from '@/stores/dialogStore'\nimport { isLoad3dNode } from '@/utils/litegraphUtil'\n\nconst inputSpecLoad3D: CustomInputSpec = {\n name: 'image',\n type: 'Load3D',\n isPreview: false\n}\n\nconst inputSpecPreview3D: CustomInputSpec = {\n name: 'image',\n type: 'Preview3D',\n isPreview: true\n}\n\nasync function handleModelUpload(files: FileList, node: any) {\n if (!files?.length) return\n\n const modelWidget = node.widgets?.find(\n (w: any) => w.name === 'model_file'\n ) as IStringWidget\n\n try {\n const resourceFolder = (node.properties['Resource Folder'] as string) || ''\n\n const subfolder = resourceFolder.trim()\n ? `3d/${resourceFolder.trim()}`\n : '3d'\n\n const uploadPath = await Load3dUtils.uploadFile(files[0], subfolder)\n\n if (!uploadPath) {\n useToastStore().addAlert(t('toastMessages.fileUploadFailed'))\n return\n }\n\n const modelUrl = api.apiURL(\n Load3dUtils.getResourceURL(\n ...Load3dUtils.splitFilePath(uploadPath),\n 'input'\n )\n )\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n try {\n load3d.loadModel(modelUrl)\n } catch (error) {\n useToastStore().addAlert(t('toastMessages.failedToLoadModel'))\n }\n })\n\n if (uploadPath && modelWidget) {\n if (!modelWidget.options?.values?.includes(uploadPath)) {\n modelWidget.options?.values?.push(uploadPath)\n }\n\n modelWidget.value = uploadPath\n }\n } catch (error) {\n console.error('Model upload failed:', error)\n useToastStore().addAlert(t('toastMessages.fileUploadFailed'))\n }\n}\n\nasync function handleResourcesUpload(files: FileList, node: any) {\n if (!files?.length) return\n\n try {\n const resourceFolder = (node.properties['Resource Folder'] as string) || ''\n\n const subfolder = resourceFolder.trim()\n ? `3d/${resourceFolder.trim()}`\n : '3d'\n\n await Load3dUtils.uploadMultipleFiles(files, subfolder)\n } catch (error) {\n console.error('Extra resources upload failed:', error)\n useToastStore().addAlert(t('toastMessages.extraResourcesUploadFailed'))\n }\n}\n\nfunction createFileInput(\n accept: string,\n multiple: boolean = false\n): HTMLInputElement {\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = accept\n input.multiple = multiple\n input.style.display = 'none'\n return input\n}\n\nuseExtensionService().registerExtension({\n name: 'Comfy.Load3D',\n settings: [\n {\n id: 'Comfy.Load3D.ShowGrid',\n category: ['3D', 'Scene', 'Initial Grid Visibility'],\n name: 'Initial Grid Visibility',\n tooltip:\n 'Controls whether the grid is visible by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.',\n type: 'boolean',\n defaultValue: true,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.BackgroundColor',\n category: ['3D', 'Scene', 'Initial Background Color'],\n name: 'Initial Background Color',\n tooltip:\n 'Controls the default background color of the 3D scene. This setting determines the background appearance when a new 3D widget is created, but can be adjusted individually for each widget after creation.',\n type: 'color',\n defaultValue: '282828',\n experimental: true\n },\n {\n id: 'Comfy.Load3D.CameraType',\n category: ['3D', 'Camera', 'Initial Camera Type'],\n name: 'Initial Camera Type',\n tooltip:\n 'Controls whether the camera is perspective or orthographic by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.',\n type: 'combo',\n options: ['perspective', 'orthographic'],\n defaultValue: 'perspective',\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightIntensity',\n category: ['3D', 'Light', 'Initial Light Intensity'],\n name: 'Initial Light Intensity',\n tooltip:\n 'Sets the default brightness level of lighting in the 3D scene. This value determines how intensely lights illuminate objects when a new 3D widget is created, but can be adjusted individually for each widget after creation.',\n type: 'number',\n defaultValue: 3,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightIntensityMaximum',\n category: ['3D', 'Light', 'Light Intensity Maximum'],\n name: 'Light Intensity Maximum',\n tooltip:\n 'Sets the maximum allowable light intensity value for 3D scenes. This defines the upper brightness limit that can be set when adjusting lighting in any 3D widget.',\n type: 'number',\n defaultValue: 10,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightIntensityMinimum',\n category: ['3D', 'Light', 'Light Intensity Minimum'],\n name: 'Light Intensity Minimum',\n tooltip:\n 'Sets the minimum allowable light intensity value for 3D scenes. This defines the lower brightness limit that can be set when adjusting lighting in any 3D widget.',\n type: 'number',\n defaultValue: 1,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightAdjustmentIncrement',\n category: ['3D', 'Light', 'Light Adjustment Increment'],\n name: 'Light Adjustment Increment',\n tooltip:\n 'Controls the increment size when adjusting light intensity in 3D scenes. A smaller step value allows for finer control over lighting adjustments, while a larger value results in more noticeable changes per adjustment.',\n type: 'slider',\n attrs: {\n min: 0.1,\n max: 1,\n step: 0.1\n },\n defaultValue: 0.5,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.3DViewerEnable',\n category: ['3D', '3DViewer', 'Enable'],\n name: 'Enable 3D Viewer (Beta)',\n tooltip:\n 'Enables the 3D Viewer (Beta) for selected nodes. This feature allows you to visualize and interact with 3D models directly within the full size 3d viewer.',\n type: 'boolean',\n defaultValue: false,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.PLYEngine',\n category: ['3D', 'PLY', 'PLY Engine'],\n name: 'PLY Engine',\n tooltip:\n 'Select the engine for loading PLY files. \"threejs\" uses the native Three.js PLYLoader (best for mesh PLY files). \"fastply\" uses an optimized loader for ASCII point cloud PLY files. \"sparkjs\" uses Spark.js for 3D Gaussian Splatting PLY files.',\n type: 'combo',\n options: ['threejs', 'fastply', 'sparkjs'],\n defaultValue: 'threejs',\n experimental: true\n }\n ],\n commands: [\n {\n id: 'Comfy.3DViewer.Open3DViewer',\n icon: 'pi pi-pencil',\n label: 'Open 3D Viewer (Beta) for Selected Node',\n function: () => {\n const selectedNodes = app.canvas.selected_nodes\n if (!selectedNodes || Object.keys(selectedNodes).length !== 1) return\n\n const selectedNode = selectedNodes[Object.keys(selectedNodes)[0]]\n\n if (!isLoad3dNode(selectedNode)) return\n\n ComfyApp.copyToClipspace(selectedNode)\n // @ts-expect-error clipspace_return_node is an extension property added at runtime\n ComfyApp.clipspace_return_node = selectedNode\n\n const props = { node: selectedNode }\n\n useDialogStore().showDialog({\n key: 'global-load3d-viewer',\n title: t('load3d.viewer.title'),\n component: Load3DViewerContent,\n props: props,\n dialogComponentProps: {\n style: 'width: 80vw; height: 80vh;',\n maximizable: true,\n onClose: async () => {\n await useLoad3dService().handleViewerClose(props.node)\n }\n }\n })\n }\n }\n ],\n getCustomWidgets() {\n return {\n LOAD_3D(node) {\n const fileInput = createFileInput(\n '.gltf,.glb,.obj,.fbx,.stl,.ply,.spz,.splat,.ksplat',\n false\n )\n\n node.properties['Resource Folder'] = ''\n\n fileInput.onchange = async () => {\n await handleModelUpload(fileInput.files!, node)\n }\n\n node.addWidget('button', 'upload 3d model', 'upload3dmodel', () => {\n fileInput.click()\n })\n\n const resourcesInput = createFileInput('*', true)\n\n resourcesInput.onchange = async () => {\n await handleResourcesUpload(resourcesInput.files!, node)\n resourcesInput.value = ''\n }\n\n node.addWidget(\n 'button',\n 'upload extra resources',\n 'uploadExtraResources',\n () => {\n resourcesInput.click()\n }\n )\n\n node.addWidget('button', 'clear', 'clear', () => {\n useLoad3d(node).waitForLoad3d((load3d) => {\n load3d.clearModel()\n })\n\n const modelWidget = node.widgets?.find((w) => w.name === 'model_file')\n if (modelWidget) {\n modelWidget.value = ''\n }\n })\n\n const widget = new ComponentWidgetImpl({\n node: node,\n name: 'image',\n component: Load3D,\n inputSpec: inputSpecLoad3D,\n options: {}\n })\n\n widget.type = 'load3D'\n\n addWidget(node, widget)\n\n return { widget }\n }\n }\n },\n\n getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] {\n // Only show menu items for Load3D nodes\n if (node.constructor.comfyClass !== 'Load3D') return []\n\n const load3d = useLoad3dService().getLoad3d(node)\n if (!load3d) return []\n\n if (load3d.isSplatModel()) return []\n\n return createExportMenuItems(load3d)\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'Load3D') return\n\n const [oldWidth, oldHeight] = node.size\n\n node.setSize([Math.max(oldWidth, 300), Math.max(oldHeight, 600)])\n\n await nextTick()\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n const cameraConfig = node.properties['Camera Config'] as any\n const cameraState = cameraConfig?.state\n\n const config = new Load3DConfiguration(load3d, node.properties)\n\n const modelWidget = node.widgets?.find((w) => w.name === 'model_file')\n const width = node.widgets?.find((w) => w.name === 'width')\n const height = node.widgets?.find((w) => w.name === 'height')\n const sceneWidget = node.widgets?.find((w) => w.name === 'image')\n\n if (modelWidget && width && height && sceneWidget) {\n const settings = {\n loadFolder: 'input',\n modelWidget: modelWidget,\n cameraState: cameraState,\n width: width,\n height: height\n }\n config.configure(settings)\n\n sceneWidget.serializeValue = async () => {\n const currentLoad3d = nodeToLoad3dMap.get(node)\n if (!currentLoad3d) {\n console.error('No load3d instance found for node')\n return null\n }\n\n const cameraConfig = (node.properties['Camera Config'] as any) || {\n cameraType: currentLoad3d.getCurrentCameraType(),\n fov: currentLoad3d.cameraManager.perspectiveCamera.fov\n }\n cameraConfig.state = currentLoad3d.getCameraState()\n node.properties['Camera Config'] = cameraConfig\n\n currentLoad3d.stopRecording()\n\n const {\n scene: imageData,\n mask: maskData,\n normal: normalData\n } = await currentLoad3d.captureScene(\n width.value as number,\n height.value as number\n )\n\n const [data, dataMask, dataNormal] = await Promise.all([\n Load3dUtils.uploadTempImage(imageData, 'scene'),\n Load3dUtils.uploadTempImage(maskData, 'scene_mask'),\n Load3dUtils.uploadTempImage(normalData, 'scene_normal')\n ])\n\n currentLoad3d.handleResize()\n\n const returnVal = {\n image: `threed/${data.name} [temp]`,\n mask: `threed/${dataMask.name} [temp]`,\n normal: `threed/${dataNormal.name} [temp]`,\n camera_info:\n (node.properties['Camera Config'] as any)?.state || null,\n recording: ''\n }\n\n const recordingData = currentLoad3d.getRecordingData()\n\n if (recordingData) {\n const [recording] = await Promise.all([\n Load3dUtils.uploadTempImage(recordingData, 'recording', 'mp4')\n ])\n returnVal['recording'] = `threed/${recording.name} [temp]`\n }\n\n return returnVal\n }\n }\n })\n }\n})\n\nuseExtensionService().registerExtension({\n name: 'Comfy.Preview3D',\n\n async beforeRegisterNodeDef(_nodeType, nodeData) {\n if ('Preview3D' === nodeData.name) {\n // @ts-expect-error InputSpec is not typed correctly\n nodeData.input.required.image = ['PREVIEW_3D']\n }\n },\n\n getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] {\n // Only show menu items for Preview3D nodes\n if (node.constructor.comfyClass !== 'Preview3D') return []\n\n const load3d = useLoad3dService().getLoad3d(node)\n if (!load3d) return []\n\n if (load3d.isSplatModel()) return []\n\n return createExportMenuItems(load3d)\n },\n\n getCustomWidgets() {\n return {\n PREVIEW_3D(node) {\n const widget = new ComponentWidgetImpl({\n node,\n name: inputSpecPreview3D.name,\n component: Load3D,\n inputSpec: inputSpecPreview3D,\n options: {}\n })\n\n widget.type = 'load3D'\n\n addWidget(node, widget)\n\n return { widget }\n }\n }\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'Preview3D') return\n\n const [oldWidth, oldHeight] = node.size\n\n node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 550)])\n\n await nextTick()\n\n const onExecuted = node.onExecuted\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n const config = new Load3DConfiguration(load3d, node.properties)\n\n const modelWidget = node.widgets?.find((w) => w.name === 'model_file')\n\n if (modelWidget) {\n const lastTimeModelFile = node.properties['Last Time Model File']\n\n if (lastTimeModelFile) {\n modelWidget.value = lastTimeModelFile\n\n const cameraConfig = node.properties['Camera Config'] as any\n const cameraState = cameraConfig?.state\n\n const settings = {\n loadFolder: 'output',\n modelWidget: modelWidget,\n cameraState: cameraState\n }\n\n config.configure(settings)\n }\n\n node.onExecuted = function (message: any) {\n onExecuted?.apply(this, arguments as any)\n\n let filePath = message.result[0]\n\n if (!filePath) {\n const msg = t('toastMessages.unableToGetModelFilePath')\n console.error(msg)\n useToastStore().addAlert(msg)\n }\n\n let cameraState = message.result[1]\n let bgImagePath = message.result[2]\n\n modelWidget.value = filePath.replaceAll('\\\\', '/')\n\n node.properties['Last Time Model File'] = modelWidget.value\n\n const settings = {\n loadFolder: 'output',\n modelWidget: modelWidget,\n cameraState: cameraState,\n bgImagePath: bgImagePath\n }\n\n config.configure(settings)\n\n if (bgImagePath) {\n load3d.setBackgroundImage(bgImagePath)\n }\n }\n }\n })\n }\n})\n","import _ from 'es-toolkit/compat'\nimport type { LGraphNode } from '@/lib/litegraph/src/litegraph'\n\nimport { app, ComfyApp } from '@/scripts/app'\nimport { useMaskEditorStore } from '@/stores/maskEditorStore'\nimport { useDialogStore } from '@/stores/dialogStore'\nimport { useMaskEditor } from '@/composables/maskeditor/useMaskEditor'\n\nfunction openMaskEditor(node: LGraphNode): void {\n if (!node) {\n console.error('[MaskEditor] No node provided')\n return\n }\n\n if (!node.imgs?.length && node.previewMediaType !== 'image') {\n console.error('[MaskEditor] Node has no images')\n return\n }\n\n useMaskEditor().openMaskEditor(node)\n}\n\n// Open mask editor from clipspace (for plugin compatibility)\n// This is called when ComfyApp.open_maskeditor() is invoked without arguments\nfunction openMaskEditorFromClipspace(): void {\n const node = ComfyApp.clipspace_return_node as LGraphNode | null\n if (!node) {\n console.error('[MaskEditor] No clipspace_return_node found')\n return\n }\n\n openMaskEditor(node)\n}\n\n// Check if the dialog is already opened\nfunction isOpened(): boolean {\n return useDialogStore().isDialogOpen('global-mask-editor')\n}\n\nconst changeBrushSize = async (sizeChanger: (oldSize: number) => number) => {\n if (!isOpened()) return\n\n const store = useMaskEditorStore()\n const oldBrushSize = store.brushSettings.size\n const newBrushSize = sizeChanger(oldBrushSize)\n store.setBrushSize(newBrushSize)\n}\n\napp.registerExtension({\n name: 'Comfy.MaskEditor',\n settings: [\n {\n id: 'Comfy.MaskEditor.BrushAdjustmentSpeed',\n category: ['Mask Editor', 'BrushAdjustment', 'Sensitivity'],\n name: 'Brush adjustment speed multiplier',\n tooltip:\n 'Controls how quickly the brush size and hardness change when adjusting. Higher values mean faster changes.',\n type: 'slider',\n attrs: {\n min: 0.1,\n max: 2.0,\n step: 0.1\n },\n defaultValue: 1.0,\n versionAdded: '1.0.0'\n },\n {\n id: 'Comfy.MaskEditor.UseDominantAxis',\n category: ['Mask Editor', 'BrushAdjustment', 'UseDominantAxis'],\n name: 'Lock brush adjustment to dominant axis',\n tooltip:\n 'When enabled, brush adjustments will only affect size OR hardness based on which direction you move more',\n type: 'boolean',\n defaultValue: true\n }\n ],\n commands: [\n {\n id: 'Comfy.MaskEditor.OpenMaskEditor',\n icon: 'pi pi-pencil',\n label: 'Open Mask Editor for Selected Node',\n function: () => {\n const selectedNodes = app.canvas.selected_nodes\n if (!selectedNodes || Object.keys(selectedNodes).length !== 1) return\n\n const selectedNode = selectedNodes[Object.keys(selectedNodes)[0]]\n openMaskEditor(selectedNode)\n }\n },\n {\n id: 'Comfy.MaskEditor.BrushSize.Increase',\n icon: 'pi pi-plus-circle',\n label: 'Increase Brush Size in MaskEditor',\n function: () => changeBrushSize((old) => _.clamp(old + 2, 1, 250))\n },\n {\n id: 'Comfy.MaskEditor.BrushSize.Decrease',\n icon: 'pi pi-minus-circle',\n label: 'Decrease Brush Size in MaskEditor',\n function: () => changeBrushSize((old) => _.clamp(old - 2, 1, 250))\n },\n {\n id: 'Comfy.MaskEditor.ColorPicker',\n icon: 'pi pi-palette',\n label: 'Open Color Picker in MaskEditor',\n function: () => {\n if (!isOpened()) return\n\n const store = useMaskEditorStore()\n store.colorInput?.click()\n }\n }\n ],\n init() {\n // Set up ComfyApp static methods for plugin compatibility (deprecated)\n ComfyApp.open_maskeditor = openMaskEditorFromClipspace\n\n console.warn(\n '[MaskEditor] ComfyApp.open_maskeditor is deprecated. ' +\n 'Plugins should migrate to using the command system or direct node context menu integration.'\n )\n }\n})\n","import { downloadBlob } from '@/base/common/downloadUtil'\nimport { t } from '@/i18n'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport type { LGraphCanvas } from '@/lib/litegraph/src/litegraph'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { useDialogService } from '@/services/dialogService'\nimport type { ComfyExtension } from '@/types/comfy'\nimport { deserialiseAndCreate } from '@/utils/vintageClipboard'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\nimport { $el, ComfyDialog } from '../../scripts/ui'\nimport { GroupNodeConfig, GroupNodeHandler } from './groupNode'\n\n// Adds the ability to save and add multiple nodes as a template\n// To save:\n// Select multiple nodes (ctrl + drag to select a region or ctrl+click individual nodes)\n// Right click the canvas\n// Save Node Template -> give it a name\n//\n// To add:\n// Right click the canvas\n// Node templates -> click the one to add\n//\n// To delete/rename:\n// Right click the canvas\n// Node templates -> Manage\n//\n// To rearrange:\n// Open the manage dialog and Drag and drop elements using the \"Name:\" label as handle\n\nconst id = 'Comfy.NodeTemplates'\nconst file = 'comfy.templates.json'\n\nclass ManageTemplates extends ComfyDialog {\n // @ts-expect-error fixme ts strict error\n templates: any[]\n draggedEl: HTMLElement | null\n saveVisualCue: number | null\n emptyImg: HTMLImageElement\n importInput: HTMLInputElement\n\n constructor() {\n super()\n this.load().then((v) => {\n this.templates = v\n })\n\n this.element.classList.add('comfy-manage-templates')\n this.draggedEl = null\n this.saveVisualCue = null\n this.emptyImg = new Image()\n this.emptyImg.src =\n 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='\n\n this.importInput = $el('input', {\n type: 'file',\n accept: '.json',\n multiple: true,\n style: { display: 'none' },\n parent: document.body,\n onchange: () => this.importAll()\n }) as HTMLInputElement\n }\n\n override createButtons() {\n const btns = super.createButtons()\n btns[0].textContent = 'Close'\n btns[0].onclick = () => {\n // @ts-expect-error fixme ts strict error\n clearTimeout(this.saveVisualCue)\n this.close()\n }\n btns.unshift(\n $el('button', {\n type: 'button',\n textContent: 'Export',\n onclick: () => this.exportAll()\n })\n )\n btns.unshift(\n $el('button', {\n type: 'button',\n textContent: 'Import',\n onclick: () => {\n this.importInput.click()\n }\n })\n )\n return btns\n }\n\n async load() {\n let templates = []\n const res = await api.getUserData(file)\n if (res.status === 200) {\n try {\n templates = await res.json()\n } catch (error) {}\n } else if (res.status !== 404) {\n console.error(res.status + ' ' + res.statusText)\n }\n return templates ?? []\n }\n\n async store() {\n const templates = JSON.stringify(this.templates, undefined, 4)\n try {\n await api.storeUserData(file, templates, { stringify: false })\n } catch (error) {\n console.error(error)\n // @ts-expect-error fixme ts strict error\n useToastStore().addAlert(error.message)\n }\n }\n\n async importAll() {\n // @ts-expect-error fixme ts strict error\n for (const file of this.importInput.files) {\n if (file.type === 'application/json' || file.name.endsWith('.json')) {\n const reader = new FileReader()\n reader.onload = async () => {\n const importFile = JSON.parse(reader.result as string)\n if (importFile?.templates) {\n for (const template of importFile.templates) {\n if (template?.name && template?.data) {\n this.templates.push(template)\n }\n }\n await this.store()\n }\n }\n await reader.readAsText(file)\n }\n }\n\n // @ts-expect-error fixme ts strict error\n this.importInput.value = null\n\n this.close()\n }\n\n exportAll() {\n if (this.templates.length == 0) {\n useToastStore().addAlert(t('toastMessages.noTemplatesToExport'))\n return\n }\n\n const json = JSON.stringify({ templates: this.templates }, null, 2) // convert the data to a JSON string\n const blob = new Blob([json], { type: 'application/json' })\n downloadBlob('node_templates.json', blob)\n }\n\n override show() {\n // Show list of template names + delete button\n super.show(\n $el(\n 'div',\n {},\n this.templates.flatMap((t, i) => {\n // @ts-expect-error fixme ts strict error\n let nameInput\n return [\n $el(\n 'div',\n {\n dataset: { id: i.toString() },\n className: 'templateManagerRow',\n style: {\n display: 'grid',\n gridTemplateColumns: '1fr auto',\n border: '1px dashed transparent',\n gap: '5px',\n backgroundColor: 'var(--comfy-menu-bg)'\n },\n // @ts-expect-error fixme ts strict error\n ondragstart: (e) => {\n this.draggedEl = e.currentTarget\n e.currentTarget.style.opacity = '0.6'\n e.currentTarget.style.border = '1px dashed yellow'\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setDragImage(this.emptyImg, 0, 0)\n },\n // @ts-expect-error fixme ts strict error\n ondragend: (e) => {\n e.target.style.opacity = '1'\n e.currentTarget.style.border = '1px dashed transparent'\n e.currentTarget.removeAttribute('draggable')\n\n // rearrange the elements\n this.element\n .querySelectorAll('.templateManagerRow')\n // @ts-expect-error fixme ts strict error\n .forEach((el: HTMLElement, i) => {\n // @ts-expect-error fixme ts strict error\n var prev_i = Number.parseInt(el.dataset.id)\n\n if (el == this.draggedEl && prev_i != i) {\n this.templates.splice(\n i,\n 0,\n this.templates.splice(prev_i, 1)[0]\n )\n }\n el.dataset.id = i.toString()\n })\n this.store()\n },\n // @ts-expect-error fixme ts strict error\n ondragover: (e) => {\n e.preventDefault()\n if (e.currentTarget == this.draggedEl) return\n\n let rect = e.currentTarget.getBoundingClientRect()\n if (e.clientY > rect.top + rect.height / 2) {\n e.currentTarget.parentNode.insertBefore(\n this.draggedEl,\n e.currentTarget.nextSibling\n )\n } else {\n e.currentTarget.parentNode.insertBefore(\n this.draggedEl,\n e.currentTarget\n )\n }\n }\n },\n [\n $el(\n 'label',\n {\n textContent: 'Name: ',\n style: {\n cursor: 'grab'\n },\n // @ts-expect-error fixme ts strict error\n onmousedown: (e) => {\n // enable dragging only from the label\n if (e.target.localName == 'label')\n e.currentTarget.parentNode.draggable = 'true'\n }\n },\n [\n $el('input', {\n value: t.name,\n dataset: { name: t.name },\n style: {\n transitionProperty: 'background-color',\n transitionDuration: '0s'\n },\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n // @ts-expect-error fixme ts strict error\n clearTimeout(this.saveVisualCue)\n var el = e.target\n var row = el.parentNode.parentNode\n this.templates[row.dataset.id].name =\n el.value.trim() || 'untitled'\n this.store()\n el.style.backgroundColor = 'rgb(40, 95, 40)'\n el.style.transitionDuration = '0s'\n // @ts-expect-error\n // In browser env the return value is number.\n this.saveVisualCue = setTimeout(function () {\n el.style.transitionDuration = '.7s'\n el.style.backgroundColor = 'var(--comfy-input-bg)'\n }, 15)\n },\n // @ts-expect-error fixme ts strict error\n onkeypress: (e) => {\n var el = e.target\n // @ts-expect-error fixme ts strict error\n clearTimeout(this.saveVisualCue)\n el.style.transitionDuration = '0s'\n el.style.backgroundColor = 'var(--comfy-input-bg)'\n },\n $: (el) => (nameInput = el)\n })\n ]\n ),\n $el('div', {}, [\n $el('button', {\n textContent: 'Export',\n style: {\n fontSize: '12px',\n fontWeight: 'normal'\n },\n onclick: () => {\n const json = JSON.stringify({ templates: [t] }, null, 2) // convert the data to a JSON string\n const blob = new Blob([json], {\n type: 'application/json'\n })\n // @ts-expect-error fixme ts strict error\n const name = (nameInput.value || t.name) + '.json'\n downloadBlob(name, blob)\n }\n }),\n $el('button', {\n textContent: 'Delete',\n style: {\n fontSize: '12px',\n color: 'red',\n fontWeight: 'normal'\n },\n // @ts-expect-error fixme ts strict error\n onclick: (e) => {\n const item = e.target.parentNode.parentNode\n item.parentNode.removeChild(item)\n this.templates.splice(item.dataset.id * 1, 1)\n this.store()\n // update the rows index, setTimeout ensures that the list is updated\n var that = this\n setTimeout(function () {\n that.element\n .querySelectorAll('.templateManagerRow')\n // @ts-expect-error fixme ts strict error\n .forEach((el: HTMLElement, i) => {\n el.dataset.id = i.toString()\n })\n }, 0)\n }\n })\n ])\n ]\n )\n ]\n })\n )\n )\n }\n}\n\nconst manage = new ManageTemplates()\n\n// @ts-expect-error fixme ts strict error\nconst clipboardAction = async (cb) => {\n // We use the clipboard functions but dont want to overwrite the current user clipboard\n // Restore it after we've run our callback\n const old = localStorage.getItem('litegrapheditor_clipboard')\n await cb()\n // @ts-expect-error fixme ts strict error\n localStorage.setItem('litegrapheditor_clipboard', old)\n}\n\nconst ext: ComfyExtension = {\n name: id,\n\n getCanvasMenuItems(_canvas: LGraphCanvas): IContextMenuValue[] {\n const items: IContextMenuValue[] = []\n\n // @ts-expect-error fixme ts strict error\n items.push(null)\n items.push({\n content: `Save Selected as Template`,\n disabled: !Object.keys(app.canvas.selected_nodes || {}).length,\n callback: async () => {\n const name = await useDialogService().prompt({\n title: t('nodeTemplates.saveAsTemplate'),\n message: t('nodeTemplates.enterName'),\n defaultValue: ''\n })\n if (!name?.trim()) return\n\n clipboardAction(() => {\n app.canvas.copyToClipboard()\n let data = localStorage.getItem('litegrapheditor_clipboard')\n data = JSON.parse(data || '{}')\n const nodeIds = Object.keys(app.canvas.selected_nodes)\n for (let i = 0; i < nodeIds.length; i++) {\n const node = app.canvas.graph?.getNodeById(nodeIds[i])\n const nodeData = node?.constructor.nodeData\n\n let groupData = GroupNodeHandler.getGroupData(node)\n if (groupData) {\n groupData = groupData.nodeData\n // @ts-expect-error\n if (!data.groupNodes) {\n // @ts-expect-error\n data.groupNodes = {}\n }\n if (nodeData == null) throw new TypeError('nodeData is not set')\n // @ts-expect-error\n data.groupNodes[nodeData.name] = groupData\n // @ts-expect-error\n data.nodes[i].type = nodeData.name\n }\n }\n\n manage.templates.push({\n name,\n data: JSON.stringify(data)\n })\n manage.store()\n })\n }\n })\n\n // Map each template to a menu item\n const subItems = manage.templates.map((t) => {\n return {\n content: t.name,\n callback: () => {\n clipboardAction(async () => {\n const data = JSON.parse(t.data)\n await GroupNodeConfig.registerFromWorkflow(data.groupNodes, {})\n\n // Check for old clipboard format\n if (!data.reroutes) {\n deserialiseAndCreate(t.data, app.canvas)\n } else {\n localStorage.setItem('litegrapheditor_clipboard', t.data)\n app.canvas.pasteFromClipboard()\n }\n })\n }\n }\n })\n\n // @ts-expect-error fixme ts strict error\n subItems.push(null, {\n content: 'Manage',\n callback: () => manage.show()\n })\n\n items.push({\n content: 'Node Templates',\n submenu: {\n options: subItems\n }\n })\n\n return items\n }\n}\n\napp.registerExtension(ext)\n","import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'\nimport { LGraphNode } from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '../../scripts/app'\nimport { ComfyWidgets } from '../../scripts/widgets'\n\n// Node that add notes to your project\n\napp.registerExtension({\n name: 'Comfy.NoteNode',\n registerCustomNodes() {\n class NoteNode extends LGraphNode {\n static override category: string\n static collapsable: boolean\n static title_mode: number\n\n groupcolor = LGraphCanvas.node_colors.yellow.groupcolor\n override isVirtualNode: boolean\n\n constructor(title: string) {\n super(title)\n\n this.color = LGraphCanvas.node_colors.yellow.color\n this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor\n\n if (!this.properties) {\n this.properties = { text: '' }\n }\n ComfyWidgets.STRING(\n this,\n 'text',\n ['STRING', { default: this.properties.text, multiline: true }],\n app\n )\n\n this.serialize_widgets = true\n this.isVirtualNode = true\n }\n }\n\n // Load default visibility\n\n LiteGraph.registerNodeType(\n 'Note',\n Object.assign(NoteNode, {\n title_mode: LiteGraph.NORMAL_TITLE,\n title: 'Note',\n collapsable: true\n })\n )\n\n NoteNode.category = 'utils'\n\n /** Markdown variant of NoteNode */\n class MarkdownNoteNode extends LGraphNode {\n static override title = 'Markdown Note'\n\n groupcolor = LGraphCanvas.node_colors.yellow.groupcolor\n\n constructor(title: string) {\n super(title)\n\n this.color = LGraphCanvas.node_colors.yellow.color\n this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor\n\n if (!this.properties) {\n this.properties = { text: '' }\n }\n ComfyWidgets.MARKDOWN(\n this,\n 'text',\n ['STRING', { default: this.properties.text }],\n app\n )\n\n this.serialize_widgets = true\n this.isVirtualNode = true\n }\n }\n\n LiteGraph.registerNodeType('MarkdownNote', MarkdownNoteNode)\n MarkdownNoteNode.category = 'utils'\n }\n})\n","/*\nPreview Any - original implement from\nhttps://github.com/rgthree/rgthree-comfy/blob/main/py/display_any.py\nupstream requested in https://github.com/Kosinkadink/rfcs/blob/main/rfcs/0000-corenodes.md#preview-nodes\n */\nimport { app } from '@/scripts/app'\nimport { type DOMWidget } from '@/scripts/domWidget'\nimport { ComfyWidgets } from '@/scripts/widgets'\nimport { useExtensionService } from '@/services/extensionService'\n\nuseExtensionService().registerExtension({\n name: 'Comfy.PreviewAny',\n async beforeRegisterNodeDef(nodeType, nodeData) {\n if (nodeData.name === 'PreviewAny') {\n const onNodeCreated = nodeType.prototype.onNodeCreated\n\n nodeType.prototype.onNodeCreated = function () {\n onNodeCreated ? onNodeCreated.apply(this, []) : undefined\n\n const showValueWidget = ComfyWidgets['MARKDOWN'](\n this,\n 'preview',\n ['MARKDOWN', {}],\n app\n ).widget as DOMWidget<HTMLTextAreaElement, string>\n\n const showValueWidgetPlain = ComfyWidgets['STRING'](\n this,\n 'preview',\n ['STRING', { multiline: true }],\n app\n ).widget as DOMWidget<HTMLTextAreaElement, string>\n\n const showAsPlaintextWidget = ComfyWidgets['BOOLEAN'](\n this,\n 'previewMode',\n [\n 'BOOLEAN',\n { label_on: 'Markdown', label_off: 'Plaintext', default: false }\n ],\n app\n )\n\n showAsPlaintextWidget.widget.callback = (value) => {\n showValueWidget.hidden = !value\n showValueWidget.options.hidden = !value\n showValueWidgetPlain.hidden = value\n showValueWidgetPlain.options.hidden = value\n }\n\n showValueWidget.hidden = true\n showValueWidget.options.hidden = true\n showValueWidget.options.read_only = true\n showValueWidget.element.readOnly = true\n showValueWidget.element.disabled = true\n showValueWidget.serialize = false\n\n showValueWidgetPlain.hidden = false\n showValueWidgetPlain.options.hidden = false\n showValueWidgetPlain.options.read_only = true\n showValueWidgetPlain.element.readOnly = true\n showValueWidgetPlain.element.disabled = true\n showValueWidgetPlain.serialize = false\n }\n\n const onExecuted = nodeType.prototype.onExecuted\n\n nodeType.prototype.onExecuted = function (message) {\n onExecuted === null || onExecuted === void 0\n ? void 0\n : onExecuted.apply(this, [message])\n\n const previewWidgets =\n this.widgets?.filter((w) => w.name === 'preview') ?? []\n\n for (const previewWidget of previewWidgets) {\n const text = message.text ?? ''\n previewWidget.value = Array.isArray(text) ? (text[0] ?? '') : text\n }\n }\n }\n }\n})\n","import type { IContextMenuValue } from '@/lib/litegraph/src/litegraph'\nimport {\n LGraphCanvas,\n LGraphNode,\n LiteGraph\n} from '@/lib/litegraph/src/litegraph'\nimport type { ISlotType } from '@/lib/litegraph/src/interfaces'\n\nimport { app } from '../../scripts/app'\nimport { getWidgetConfig, mergeIfValid, setWidgetConfig } from './widgetInputs'\n\n// Node that allows you to redirect connections for cleaner graphs\n\napp.registerExtension({\n name: 'Comfy.RerouteNode',\n registerCustomNodes(app) {\n interface RerouteNode extends LGraphNode {\n __outputType?: string | number\n }\n\n class RerouteNode extends LGraphNode {\n static override category: string | undefined\n static defaultVisibility = false\n\n constructor(title?: string) {\n super(title ?? '')\n if (!this.properties) {\n this.properties = {}\n }\n this.properties.showOutputText = RerouteNode.defaultVisibility\n this.properties.horizontal = false\n\n this.addInput('', '*')\n this.addOutput(this.properties.showOutputText ? '*' : '', '*')\n\n // This node is purely frontend and does not impact the resulting prompt so should not be serialized\n this.isVirtualNode = true\n }\n override onAfterGraphConfigured() {\n requestAnimationFrame(() => {\n this.onConnectionsChange(LiteGraph.INPUT, undefined, true)\n })\n }\n override clone(): LGraphNode | null {\n const cloned = super.clone()\n if (!cloned) return cloned\n cloned.removeOutput(0)\n cloned.addOutput(this.properties.showOutputText ? '*' : '', '*')\n cloned.setSize(cloned.computeSize())\n return cloned\n }\n override onConnectionsChange(\n type: ISlotType,\n _index: number | undefined,\n connected: boolean\n ) {\n const { graph } = this\n if (!graph) return\n if (app.configuringGraph) return\n\n // Prevent multiple connections to different types when we have no input\n if (connected && type === LiteGraph.OUTPUT) {\n // Ignore wildcard nodes as these will be updated to real types\n const types = new Set(\n this.outputs[0].links\n ?.map((l) => graph.links[l]?.type)\n ?.filter((t) => t && t !== '*') ?? []\n )\n if (types.size > 1) {\n const linksToDisconnect = []\n for (const linkId of this.outputs[0].links ?? []) {\n const link = graph.links[linkId]\n linksToDisconnect.push(link)\n }\n linksToDisconnect.pop()\n for (const link of linksToDisconnect) {\n const node = graph.getNodeById(link.target_id)\n node?.disconnectInput(link.target_slot)\n }\n }\n }\n\n // Find root input\n let currentNode: RerouteNode | null = this\n let updateNodes: RerouteNode[] = []\n let inputType = null\n let inputNode = null\n while (currentNode) {\n updateNodes.unshift(currentNode)\n const linkId = currentNode.inputs[0].link\n if (linkId !== null) {\n const link = graph.links[linkId]\n if (!link) return\n const node = graph.getNodeById(link.origin_id)\n if (!node) return\n if (node instanceof RerouteNode) {\n if (node === this) {\n // We've found a circle\n currentNode.disconnectInput(link.target_slot)\n currentNode = null\n } else {\n // Move the previous node\n currentNode = node\n }\n } else {\n // We've found the end\n inputNode = currentNode\n inputType = node.outputs[link.origin_slot]?.type ?? null\n break\n }\n } else {\n // This path has no input node\n currentNode = null\n break\n }\n }\n\n // Find all outputs\n const nodes: RerouteNode[] = [this]\n let outputType = null\n while (nodes.length) {\n currentNode = nodes.pop()!\n const outputs = currentNode.outputs?.[0]?.links ?? []\n for (const linkId of outputs) {\n const link = graph.links[linkId]\n\n // When disconnecting sometimes the link is still registered\n if (!link) continue\n\n const node = graph.getNodeById(link.target_id)\n if (!node) continue\n if (node instanceof RerouteNode) {\n // Follow reroute nodes\n nodes.push(node)\n updateNodes.push(node)\n } else {\n // We've found an output\n const nodeInput = node.inputs[link.target_slot]\n const nodeOutType = nodeInput.type\n const keep =\n !inputType ||\n !nodeOutType ||\n LiteGraph.isValidConnection(inputType, nodeOutType)\n if (!keep) {\n // The output doesnt match our input so disconnect it\n node.disconnectInput(link.target_slot)\n continue\n }\n node.onConnectionsChange?.(\n LiteGraph.INPUT,\n link.target_slot,\n keep,\n link,\n nodeInput\n )\n outputType = node.inputs[link.target_slot].type\n }\n }\n }\n\n const displayType = inputType || outputType || '*'\n const color = LGraphCanvas.link_type_colors[displayType]\n\n let widgetConfig\n let widgetType\n // Update the types of each node\n for (const node of updateNodes) {\n // If we dont have an input type we are always wildcard but we'll show the output type\n // This lets you change the output link to a different type and all nodes will update\n node.outputs[0].type = inputType || '*'\n node.__outputType = displayType\n node.outputs[0].name = node.properties.showOutputText\n ? `${displayType}`\n : ''\n node.setSize(node.computeSize())\n\n for (const l of node.outputs[0].links || []) {\n const link = graph.links[l]\n if (!link) continue\n link.color = color\n\n if (app.configuringGraph) continue\n const targetNode = graph.getNodeById(link.target_id)\n if (!targetNode) continue\n const targetInput = targetNode.inputs?.[link.target_slot]\n if (targetInput?.widget) {\n const config = getWidgetConfig(targetInput)\n if (!widgetConfig) {\n widgetConfig = config[1] ?? {}\n widgetType = config[0]\n }\n\n const merged = mergeIfValid(targetInput, [\n config[0],\n widgetConfig\n ])\n if (merged.customConfig) {\n widgetConfig = merged.customConfig\n }\n }\n }\n }\n\n for (const node of updateNodes) {\n if (widgetConfig && outputType) {\n node.inputs[0].widget = { name: 'value' }\n setWidgetConfig(node.inputs[0], [\n widgetType ?? `${displayType}`,\n widgetConfig\n ])\n } else {\n setWidgetConfig(node.inputs[0], undefined)\n }\n }\n\n if (inputNode?.inputs?.[0]?.link) {\n const link = graph.links[inputNode.inputs[0].link]\n if (link) {\n link.color = color\n }\n }\n }\n\n override getExtraMenuOptions(\n _: unknown,\n options: (IContextMenuValue | null)[]\n ): IContextMenuValue[] {\n options.unshift(\n {\n content:\n (this.properties.showOutputText ? 'Hide' : 'Show') + ' Type',\n callback: () => {\n this.properties.showOutputText = !this.properties.showOutputText\n if (this.properties.showOutputText) {\n this.outputs[0].name = `${this.__outputType || this.outputs[0].type}`\n } else {\n this.outputs[0].name = ''\n }\n this.setSize(this.computeSize())\n app.canvas.setDirty(true, true)\n }\n },\n {\n content:\n (RerouteNode.defaultVisibility ? 'Hide' : 'Show') +\n ' Type By Default',\n callback: () => {\n RerouteNode.setDefaultTextVisibility(\n !RerouteNode.defaultVisibility\n )\n }\n }\n )\n return []\n }\n override computeSize(): [number, number] {\n return [\n this.properties.showOutputText && this.outputs && this.outputs.length\n ? Math.max(\n 75,\n LiteGraph.NODE_TEXT_SIZE * this.outputs[0].name.length * 0.6 +\n 40\n )\n : 75,\n 26\n ]\n }\n\n static setDefaultTextVisibility(visible: boolean) {\n RerouteNode.defaultVisibility = visible\n if (visible) {\n localStorage['Comfy.RerouteNode.DefaultVisibility'] = 'true'\n } else {\n delete localStorage['Comfy.RerouteNode.DefaultVisibility']\n }\n }\n }\n\n // Load default visibility\n RerouteNode.setDefaultTextVisibility(\n !!localStorage['Comfy.RerouteNode.DefaultVisibility']\n )\n\n LiteGraph.registerNodeType(\n 'Reroute',\n Object.assign(RerouteNode, {\n title_mode: LiteGraph.NO_TITLE,\n title: 'Reroute',\n collapsable: false\n })\n )\n\n RerouteNode.category = 'utils'\n }\n})\n","import { applyTextReplacements } from '@/utils/searchAndReplace'\n\nimport { app } from '../../scripts/app'\n\nconst saveNodeTypes = new Set([\n 'SaveImage',\n 'SaveVideo',\n 'SaveAnimatedWEBP',\n 'SaveWEBM',\n 'SaveAudio',\n 'SaveGLB',\n 'SaveAnimatedPNG',\n 'CLIPSave',\n 'VAESave',\n 'ModelSave',\n 'LoraSave',\n 'SaveLatent'\n])\n\n// Use widget values and dates in output filenames\n\napp.registerExtension({\n name: 'Comfy.SaveImageExtraOutput',\n async beforeRegisterNodeDef(nodeType, nodeData, app) {\n if (saveNodeTypes.has(nodeData.name)) {\n const onNodeCreated = nodeType.prototype.onNodeCreated\n // When the SaveImage node is created we want to override the serialization of the output name widget to run our S&R\n nodeType.prototype.onNodeCreated = function () {\n const r = onNodeCreated\n ? // @ts-expect-error fixme ts strict error\n onNodeCreated.apply(this, arguments)\n : undefined\n\n // @ts-expect-error fixme ts strict error\n const widget = this.widgets.find((w) => w.name === 'filename_prefix')\n // @ts-expect-error fixme ts strict error\n widget.serializeValue = () => {\n // @ts-expect-error fixme ts strict error\n return applyTextReplacements(app.graph, widget.value)\n }\n\n return r\n }\n } else {\n // When any other node is created add a property to alias the node\n const onNodeCreated = nodeType.prototype.onNodeCreated\n nodeType.prototype.onNodeCreated = function () {\n const r = onNodeCreated\n ? // @ts-expect-error fixme ts strict error\n onNodeCreated.apply(this, arguments)\n : undefined\n\n if (!this.properties || !('Node name for S&R' in this.properties)) {\n this.addProperty('Node name for S&R', this.constructor.type, 'string')\n }\n\n return r\n }\n }\n }\n})\n","import { nextTick } from 'vue'\n\nimport Load3D from '@/components/load3d/Load3D.vue'\nimport { useLoad3d } from '@/composables/useLoad3d'\nimport { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'\nimport Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport { ComponentWidgetImpl, addWidget } from '@/scripts/domWidget'\nimport { useExtensionService } from '@/services/extensionService'\nimport { useLoad3dService } from '@/services/load3dService'\n\nconst inputSpec: CustomInputSpec = {\n name: 'image',\n type: 'Preview3D',\n isPreview: true\n}\n\nuseExtensionService().registerExtension({\n name: 'Comfy.SaveGLB',\n\n async beforeRegisterNodeDef(_nodeType, nodeData) {\n if ('SaveGLB' === nodeData.name) {\n // @ts-expect-error InputSpec is not typed correctly\n nodeData.input.required.image = ['PREVIEW_3D']\n }\n },\n\n getCustomWidgets() {\n return {\n PREVIEW_3D(node) {\n const widget = new ComponentWidgetImpl({\n node,\n name: inputSpec.name,\n component: Load3D,\n inputSpec,\n options: {}\n })\n\n widget.type = 'load3D'\n\n addWidget(node, widget)\n\n return { widget }\n }\n }\n },\n\n getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] {\n // Only show menu items for SaveGLB nodes\n if (node.constructor.comfyClass !== 'SaveGLB') return []\n\n const load3d = useLoad3dService().getLoad3d(node)\n if (!load3d) return []\n\n if (load3d.isSplatModel()) return []\n\n return createExportMenuItems(load3d)\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'SaveGLB') return\n\n const [oldWidth, oldHeight] = node.size\n\n node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 550)])\n\n await nextTick()\n\n const onExecuted = node.onExecuted\n\n node.onExecuted = function (message: any) {\n onExecuted?.apply(this, arguments as any)\n\n const fileInfo = message['3d'][0]\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n const modelWidget = node.widgets?.find((w) => w.name === 'image')\n\n if (load3d && modelWidget) {\n const filePath = fileInfo['subfolder'] + '/' + fileInfo['filename']\n\n modelWidget.value = filePath\n\n const config = new Load3DConfiguration(load3d, node.properties)\n\n config.configureForSaveMesh(fileInfo['type'], filePath)\n }\n })\n }\n }\n})\n","import { type LGraphCanvas, createBounds } from '@/lib/litegraph/src/litegraph'\nimport { app } from '@/scripts/app'\n\n/**\n * Draws a dashed border around selected items that maintains constant pixel size\n * regardless of zoom level, similar to the DOM selection overlay.\n */\nfunction drawSelectionBorder(\n ctx: CanvasRenderingContext2D,\n canvas: LGraphCanvas\n) {\n const selectedItems = canvas.selectedItems\n\n // Only draw if multiple items selected\n if (selectedItems.size <= 1) return\n\n // Use the same bounds calculation as the toolbox\n const bounds = createBounds(selectedItems, 10)\n if (!bounds) return\n\n const [x, y, width, height] = bounds\n\n // Save context state\n ctx.save()\n\n // Set up dashed line style that doesn't scale with zoom\n const borderWidth = 2 / canvas.ds.scale // Constant 2px regardless of zoom\n ctx.lineWidth = borderWidth\n ctx.strokeStyle =\n getComputedStyle(document.documentElement)\n .getPropertyValue('--border-color')\n .trim() || '#ffffff66'\n\n // Create dash pattern that maintains visual size\n const dashSize = 5 / canvas.ds.scale\n ctx.setLineDash([dashSize, dashSize])\n\n // Draw the border using the bounds directly\n ctx.beginPath()\n ctx.roundRect(x, y, width, height, 8 / canvas.ds.scale)\n ctx.stroke()\n\n // Restore context\n ctx.restore()\n}\n\n/**\n * Extension that adds a dashed selection border for multiple selected nodes\n */\nconst ext = {\n name: 'Comfy.SelectionBorder',\n\n async init() {\n // Hook into the canvas drawing\n const originalDrawForeground = app.canvas.onDrawForeground\n\n app.canvas.onDrawForeground = function (\n ctx: CanvasRenderingContext2D,\n visibleArea: any\n ) {\n // Call original if it exists\n originalDrawForeground?.call(this, ctx, visibleArea)\n\n // Draw our selection border\n drawSelectionBorder(ctx, app.canvas)\n }\n }\n}\n\napp.registerExtension(ext)\n","import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '@/scripts/app'\n\nlet touchZooming = false\nlet touchCount = 0\n\napp.registerExtension({\n name: 'Comfy.SimpleTouchSupport',\n setup() {\n let touchDist: number | null = null\n let touchTime: Date | null = null\n let lastTouch: { clientX: number; clientY: number } | null = null\n let lastScale: number | null = null\n function getMultiTouchPos(e: TouchEvent) {\n return Math.hypot(\n e.touches[0].clientX - e.touches[1].clientX,\n e.touches[0].clientY - e.touches[1].clientY\n )\n }\n\n function getMultiTouchCenter(e: TouchEvent) {\n return {\n clientX: (e.touches[0].clientX + e.touches[1].clientX) / 2,\n clientY: (e.touches[0].clientY + e.touches[1].clientY) / 2\n }\n }\n\n app.canvasEl.parentElement?.addEventListener(\n 'touchstart',\n (e: TouchEvent) => {\n touchCount += e.changedTouches.length\n\n lastTouch = null\n lastScale = null\n if (e.touches?.length === 1) {\n // Store start time for press+hold for context menu\n touchTime = new Date()\n lastTouch = e.touches[0]\n } else {\n touchTime = null\n if (e.touches?.length === 2) {\n // Store center pos for zoom\n lastScale = app.canvas.ds.scale\n lastTouch = getMultiTouchCenter(e)\n\n touchDist = getMultiTouchPos(e)\n app.canvas.pointer.isDown = false\n }\n }\n },\n true\n )\n\n app.canvasEl.parentElement?.addEventListener(\n 'touchend',\n (e: TouchEvent) => {\n touchCount -= e.changedTouches.length\n\n if (e.touches?.length !== 1) touchZooming = false\n if (touchTime && !e.touches?.length) {\n if (new Date().getTime() - touchTime.getTime() > 600) {\n if (e.target === app.canvasEl) {\n const touch = {\n button: 2, // Right click\n clientX: e.changedTouches[0].clientX,\n clientY: e.changedTouches[0].clientY,\n pointerId: 1, // changedTouches' id is 0, set it to any number\n isPrimary: true // changedTouches' isPrimary is false, so set it to true\n }\n // context menu info set in 'pointerdown' event\n app.canvasEl.dispatchEvent(new PointerEvent('pointerdown', touch))\n // then, context menu open after 'pointerup' event\n setTimeout(() => {\n app.canvasEl.dispatchEvent(new PointerEvent('pointerup', touch))\n })\n e.preventDefault()\n }\n }\n touchTime = null\n }\n }\n )\n\n const resetTouchState = () => {\n touchCount = 0\n touchZooming = false\n touchTime = null\n lastTouch = null\n lastScale = null\n touchDist = null\n }\n\n // Reset touch state when page loses visibility (e.g., switching apps on iPad)\n // This prevents touchCount from getting stuck when touchend events are missed\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) {\n resetTouchState()\n }\n })\n\n // Also handle touchcancel which fires when touch is interrupted\n app.canvasEl.parentElement?.addEventListener('touchcancel', resetTouchState)\n\n app.canvasEl.parentElement?.addEventListener(\n 'touchmove',\n (e) => {\n // make a threshold for touchmove to prevent clear touchTime for long press\n if (touchTime && lastTouch && e.touches?.length === 1) {\n const onlyTouch = e.touches[0]\n const deltaX = onlyTouch.clientX - lastTouch.clientX\n const deltaY = onlyTouch.clientY - lastTouch.clientY\n if (deltaX * deltaX + deltaY * deltaY > 30) {\n touchTime = null\n }\n }\n if (e.touches?.length === 2 && lastTouch && !e.ctrlKey && !e.shiftKey) {\n e.preventDefault() // Prevent browser from zooming when two textareas are touched\n app.canvas.pointer.isDown = false\n touchZooming = true\n\n LiteGraph.closeAllContextMenus(window)\n // @ts-expect-error\n app.canvas.search_box?.close()\n const newTouchDist = getMultiTouchPos(e)\n\n const center = getMultiTouchCenter(e)\n\n if (lastScale === null || touchDist === null) return\n let scale = (lastScale * newTouchDist) / touchDist\n\n const newX = (center.clientX - lastTouch.clientX) / scale\n const newY = (center.clientY - lastTouch.clientY) / scale\n\n // Code from LiteGraph\n if (scale < app.canvas.ds.min_scale) {\n scale = app.canvas.ds.min_scale\n } else if (scale > app.canvas.ds.max_scale) {\n scale = app.canvas.ds.max_scale\n }\n\n const oldScale = app.canvas.ds.scale\n\n app.canvas.ds.scale = scale\n\n // Code from LiteGraph\n if (Math.abs(app.canvas.ds.scale - 1) < 0.01) {\n app.canvas.ds.scale = 1\n }\n\n const newScale = app.canvas.ds.scale\n\n const convertScaleToOffset = (scale: number) => [\n center.clientX / scale - app.canvas.ds.offset[0],\n center.clientY / scale - app.canvas.ds.offset[1]\n ]\n var oldCenter = convertScaleToOffset(oldScale)\n var newCenter = convertScaleToOffset(newScale)\n\n app.canvas.ds.offset[0] += newX + newCenter[0] - oldCenter[0]\n app.canvas.ds.offset[1] += newY + newCenter[1] - oldCenter[1]\n\n lastTouch.clientX = center.clientX\n lastTouch.clientY = center.clientY\n\n app.canvas.setDirty(true, true)\n }\n },\n true\n )\n }\n})\n\nconst processMouseDown = LGraphCanvas.prototype.processMouseDown\nLGraphCanvas.prototype.processMouseDown = function (e: PointerEvent) {\n if (touchZooming || touchCount) {\n return\n }\n app.canvas.pointer.isDown = false // Prevent context menu from opening on second tap\n return processMouseDown.apply(this, [e])\n}\n\nconst processMouseMove = LGraphCanvas.prototype.processMouseMove\nLGraphCanvas.prototype.processMouseMove = function (e: PointerEvent) {\n if (touchZooming || touchCount > 1) {\n return\n }\n return processMouseMove.apply(this, [e])\n}\n","import { LiteGraph } from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '../../scripts/app'\nimport { ComfyWidgets } from '../../scripts/widgets'\n\n// Adds defaults for quickly adding nodes with middle click on the input/output\n\napp.registerExtension({\n name: 'Comfy.SlotDefaults',\n suggestionsNumber: null,\n init() {\n LiteGraph.search_filter_enabled = true\n LiteGraph.middle_click_slot_add_default_node = true\n this.suggestionsNumber = app.ui.settings.addSetting({\n id: 'Comfy.NodeSuggestions.number',\n category: ['Comfy', 'Node Search Box', 'NodeSuggestions'],\n name: 'Number of nodes suggestions',\n tooltip: 'Only for litegraph searchbox/context menu',\n type: 'slider',\n attrs: {\n min: 1,\n max: 100,\n step: 1\n },\n defaultValue: 5,\n onChange: (newVal) => {\n this.setDefaults(newVal)\n }\n })\n },\n slot_types_default_out: {},\n slot_types_default_in: {},\n async beforeRegisterNodeDef(nodeType, nodeData) {\n var nodeId = nodeData.name\n const inputs = nodeData['input']?.['required'] //only show required inputs to reduce the mess also not logical to create node with optional inputs\n for (const inputKey in inputs) {\n var input = inputs[inputKey]\n if (typeof input[0] !== 'string') continue\n\n var type = input[0]\n if (type in ComfyWidgets) {\n var customProperties = input[1]\n if (!customProperties?.forceInput) continue //ignore widgets that don't force input\n }\n\n if (!(type in this.slot_types_default_out)) {\n this.slot_types_default_out[type] = ['Reroute']\n }\n if (this.slot_types_default_out[type].includes(nodeId)) continue\n this.slot_types_default_out[type].push(nodeId)\n\n // Input types have to be stored as lower case\n // Store each node that can handle this input type\n const lowerType = type.toLocaleLowerCase()\n if (!(lowerType in LiteGraph.registered_slot_in_types)) {\n LiteGraph.registered_slot_in_types[lowerType] = { nodes: [] }\n }\n LiteGraph.registered_slot_in_types[lowerType].nodes.push(\n // @ts-expect-error ComfyNode\n nodeType.comfyClass\n )\n }\n\n var outputs = nodeData['output'] ?? []\n for (const el of outputs) {\n const type = el as string\n if (!(type in this.slot_types_default_in)) {\n this.slot_types_default_in[type] = ['Reroute']\n }\n\n if (this.slot_types_default_in[type].includes(nodeId)) continue\n this.slot_types_default_in[type].push(nodeId)\n\n // Store each node that can handle this output type\n if (!(type in LiteGraph.registered_slot_out_types)) {\n LiteGraph.registered_slot_out_types[type] = { nodes: [] }\n }\n // @ts-expect-error ComfyNode\n LiteGraph.registered_slot_out_types[type].nodes.push(nodeType.comfyClass)\n\n if (!LiteGraph.slot_types_out.includes(type)) {\n LiteGraph.slot_types_out.push(type)\n }\n }\n\n var maxNum = this.suggestionsNumber.value\n this.setDefaults(maxNum)\n },\n setDefaults(maxNum?: number | null) {\n LiteGraph.slot_types_default_out = {}\n LiteGraph.slot_types_default_in = {}\n\n for (const type in this.slot_types_default_out) {\n LiteGraph.slot_types_default_out[type] = this.slot_types_default_out[\n type\n ].slice(0, maxNum)\n }\n for (const type in this.slot_types_default_in) {\n LiteGraph.slot_types_default_in[type] = this.slot_types_default_in[\n type\n ].slice(0, maxNum)\n }\n }\n})\n","import { MediaRecorder as ExtendableMediaRecorder } from 'extendable-media-recorder'\n\nimport { useChainCallback } from '@/composables/functional/useChainCallback'\nimport { useNodeDragAndDrop } from '@/composables/node/useNodeDragAndDrop'\nimport { useNodeFileInput } from '@/composables/node/useNodeFileInput'\nimport { useNodePaste } from '@/composables/node/useNodePaste'\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/litegraph'\nimport type {\n IBaseWidget,\n IStringWidget\n} from '@/lib/litegraph/src/types/widgets'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport {\n getResourceURL,\n splitFilePath\n} from '@/renderer/extensions/vueNodes/widgets/utils/audioUtils'\nimport type { ComfyNodeDef } from '@/schemas/nodeDefSchema'\nimport type { DOMWidget } from '@/scripts/domWidget'\nimport { useAudioService } from '@/services/audioService'\nimport { type NodeLocatorId } from '@/types'\nimport { getNodeByLocatorId } from '@/utils/graphTraversalUtil'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\n\nasync function uploadFile(\n audioWidget: IStringWidget,\n audioUIWidget: DOMWidget<HTMLAudioElement, string>,\n file: File,\n updateNode: boolean,\n pasted: boolean = false\n) {\n try {\n // Wrap file in formdata so it includes filename\n const body = new FormData()\n body.append('image', file)\n if (pasted) body.append('subfolder', 'pasted')\n const resp = await api.fetchApi('/upload/image', {\n method: 'POST',\n body\n })\n\n if (resp.status === 200) {\n const data = await resp.json()\n // Add the file to the dropdown list and update the widget value\n let path = data.name\n if (data.subfolder) path = data.subfolder + '/' + path\n\n // @ts-expect-error fixme ts strict error\n if (!audioWidget.options.values.includes(path)) {\n // @ts-expect-error fixme ts strict error\n audioWidget.options.values.push(path)\n }\n\n if (updateNode) {\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(...splitFilePath(path))\n )\n audioWidget.value = path\n\n // Manually trigger the callback to update VueNodes\n audioWidget.callback?.(path)\n }\n } else {\n useToastStore().addAlert(resp.status + ' - ' + resp.statusText)\n }\n } catch (error) {\n // @ts-expect-error fixme ts strict error\n useToastStore().addAlert(error)\n }\n}\n\n// AudioWidget MUST be registered first, as AUDIOUPLOAD depends on AUDIO_UI to be\n// present.\napp.registerExtension({\n name: 'Comfy.AudioWidget',\n async beforeRegisterNodeDef(nodeType, nodeData) {\n if (\n [\n 'LoadAudio',\n 'SaveAudio',\n 'PreviewAudio',\n 'SaveAudioMP3',\n 'SaveAudioOpus'\n ].includes(\n // @ts-expect-error fixme ts strict error\n nodeType.prototype.comfyClass\n )\n ) {\n // @ts-expect-error fixme ts strict error\n nodeData.input.required.audioUI = ['AUDIO_UI', {}]\n }\n },\n getCustomWidgets() {\n return {\n AUDIO_UI(node: LGraphNode, inputName: string) {\n const audio = document.createElement('audio')\n audio.controls = true\n audio.classList.add('comfy-audio')\n audio.setAttribute('name', 'media')\n\n const audioUIWidget: DOMWidget<HTMLAudioElement, string> =\n node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)\n audioUIWidget.serialize = false\n const { nodeData } = node.constructor\n if (nodeData == null) throw new TypeError('nodeData is null')\n\n const isOutputNode = nodeData.output_node\n if (isOutputNode) {\n // Hide the audio widget when there is no audio initially.\n audioUIWidget.element.classList.add('empty-audio-widget')\n // Populate the audio widget UI on node execution.\n const onExecuted = node.onExecuted\n node.onExecuted = function (message: any) {\n // @ts-expect-error fixme ts strict error\n onExecuted?.apply(this, arguments)\n const audios = message.audio\n if (!audios) return\n const audio = audios[0]\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(audio.subfolder, audio.filename, audio.type)\n )\n audioUIWidget.element.classList.remove('empty-audio-widget')\n }\n }\n\n audioUIWidget.onRemove = useChainCallback(\n audioUIWidget.onRemove,\n () => {\n if (!audioUIWidget.element) return\n audioUIWidget.element.pause()\n audioUIWidget.element.src = ''\n audioUIWidget.element.remove()\n }\n )\n\n return { widget: audioUIWidget }\n }\n }\n },\n onNodeOutputsUpdated(nodeOutputs: Record<NodeLocatorId, any>) {\n for (const [nodeLocatorId, output] of Object.entries(nodeOutputs)) {\n if ('audio' in output) {\n const node = getNodeByLocatorId(app.rootGraph, nodeLocatorId)\n if (!node) continue\n\n // @ts-expect-error fixme ts strict error\n const audioUIWidget = node.widgets.find(\n (w) => w.name === 'audioUI'\n ) as unknown as DOMWidget<HTMLAudioElement, string>\n const audio = output.audio[0]\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(audio.subfolder, audio.filename, audio.type)\n )\n audioUIWidget.element.classList.remove('empty-audio-widget')\n }\n }\n }\n})\n\napp.registerExtension({\n name: 'Comfy.UploadAudio',\n async beforeRegisterNodeDef(_nodeType, nodeData: ComfyNodeDef) {\n if (nodeData?.input?.required?.audio?.[1]?.audio_upload === true) {\n nodeData.input.required.upload = ['AUDIOUPLOAD', {}]\n }\n },\n getCustomWidgets() {\n return {\n AUDIOUPLOAD(node, inputName: string) {\n // The widget that allows user to select file.\n // @ts-expect-error fixme ts strict error\n const audioWidget = node.widgets.find(\n (w) => w.name === 'audio'\n ) as IStringWidget\n // @ts-expect-error fixme ts strict error\n const audioUIWidget = node.widgets.find(\n (w) => w.name === 'audioUI'\n ) as unknown as DOMWidget<HTMLAudioElement, string>\n audioUIWidget.options.canvasOnly = true\n\n const onAudioWidgetUpdate = () => {\n if (typeof audioWidget.value !== 'string') return\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(...splitFilePath(audioWidget.value))\n )\n }\n // Initially load default audio file to audioUIWidget.\n if (audioWidget.value) {\n onAudioWidgetUpdate()\n }\n audioWidget.callback = onAudioWidgetUpdate\n\n // Load saved audio file widget values if restoring from workflow\n const onGraphConfigured = node.onGraphConfigured\n node.onGraphConfigured = function () {\n // @ts-expect-error fixme ts strict error\n onGraphConfigured?.apply(this, arguments)\n if (audioWidget.value) {\n onAudioWidgetUpdate()\n }\n }\n\n const handleUpload = async (files: File[]) => {\n if (files?.length) {\n uploadFile(audioWidget, audioUIWidget, files[0], true)\n }\n return files\n }\n\n const isAudioFile = (file: File) => file.type.startsWith('audio/')\n\n const { openFileSelection } = useNodeFileInput(node, {\n accept: 'audio/*',\n onSelect: handleUpload\n })\n\n // The widget to pop up the upload dialog.\n const uploadWidget = node.addWidget(\n 'button',\n inputName,\n '',\n openFileSelection,\n { serialize: false, canvasOnly: true }\n )\n uploadWidget.label = t('g.choose_file_to_upload')\n\n useNodeDragAndDrop(node, {\n fileFilter: isAudioFile,\n onDrop: handleUpload\n })\n\n useNodePaste(node, {\n fileFilter: isAudioFile,\n onPaste: handleUpload\n })\n\n node.previewMediaType = 'audio'\n\n return { widget: uploadWidget }\n }\n }\n }\n})\n\napp.registerExtension({\n name: 'Comfy.RecordAudio',\n\n getCustomWidgets() {\n return {\n AUDIO_RECORD(node, inputName: string) {\n const audio = document.createElement('audio')\n audio.controls = true\n audio.classList.add('comfy-audio')\n audio.setAttribute('name', 'media')\n const audioUIWidget: DOMWidget<HTMLAudioElement, string> =\n node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)\n audioUIWidget.options.canvasOnly = false\n\n let mediaRecorder: MediaRecorder | null = null\n let isRecording = false\n let audioChunks: Blob[] = []\n let currentStream: MediaStream | null = null\n let recordWidget: IBaseWidget | null = null\n\n let stopPromise: Promise<void> | null = null\n let stopResolve: (() => void) | null = null\n\n audioUIWidget.serializeValue = async () => {\n if (isRecording && mediaRecorder) {\n stopPromise = new Promise((resolve) => {\n stopResolve = resolve\n })\n\n mediaRecorder.stop()\n\n await stopPromise\n }\n\n const audioSrc = audioUIWidget.element.src\n\n if (!audioSrc) {\n useToastStore().addAlert(t('g.noAudioRecorded'))\n return ''\n }\n\n const blob = await fetch(audioSrc).then((r) => r.blob())\n\n return await useAudioService().convertBlobToFileAndSubmit(blob)\n }\n\n recordWidget = node.addWidget(\n 'button',\n inputName,\n '',\n async () => {\n if (!isRecording) {\n try {\n currentStream = await navigator.mediaDevices.getUserMedia({\n audio: true\n })\n\n mediaRecorder = new ExtendableMediaRecorder(currentStream, {\n mimeType: 'audio/wav'\n }) as unknown as MediaRecorder\n\n audioChunks = []\n\n mediaRecorder.ondataavailable = (event) => {\n audioChunks.push(event.data)\n }\n\n mediaRecorder.onstop = async () => {\n const audioBlob = new Blob(audioChunks, { type: 'audio/wav' })\n\n useAudioService().stopAllTracks(currentStream)\n\n if (\n audioUIWidget.element.src &&\n audioUIWidget.element.src.startsWith('blob:')\n ) {\n URL.revokeObjectURL(audioUIWidget.element.src)\n }\n\n audioUIWidget.element.src = URL.createObjectURL(audioBlob)\n\n isRecording = false\n\n if (recordWidget) {\n recordWidget.label = t('g.startRecording')\n }\n\n if (stopResolve) {\n stopResolve()\n stopResolve = null\n stopPromise = null\n }\n }\n\n mediaRecorder.onerror = (event) => {\n console.error('MediaRecorder error:', event)\n useAudioService().stopAllTracks(currentStream)\n isRecording = false\n\n if (recordWidget) {\n recordWidget.label = t('g.startRecording')\n }\n\n if (stopResolve) {\n stopResolve()\n stopResolve = null\n stopPromise = null\n }\n }\n\n mediaRecorder.start()\n isRecording = true\n if (recordWidget) {\n recordWidget.label = t('g.stopRecording')\n }\n } catch (err) {\n console.error('Error accessing microphone:', err)\n useToastStore().addAlert(t('g.micPermissionDenied'))\n\n if (mediaRecorder) {\n try {\n mediaRecorder.stop()\n } catch {}\n }\n useAudioService().stopAllTracks(currentStream)\n currentStream = null\n isRecording = false\n if (recordWidget) {\n recordWidget.label = t('g.startRecording')\n }\n }\n } else if (mediaRecorder && isRecording) {\n mediaRecorder.stop()\n }\n },\n { serialize: false, canvasOnly: false }\n )\n\n recordWidget.label = t('g.startRecording')\n // Override the type for Vue rendering while keeping 'button' for LiteGraph\n recordWidget.type = 'audiorecord'\n\n const originalOnRemoved = node.onRemoved\n node.onRemoved = function () {\n if (isRecording && mediaRecorder) {\n mediaRecorder.stop()\n }\n useAudioService().stopAllTracks(currentStream)\n if (audioUIWidget.element.src?.startsWith('blob:')) {\n URL.revokeObjectURL(audioUIWidget.element.src)\n }\n originalOnRemoved?.call(this)\n }\n\n return { widget: recordWidget }\n }\n }\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'RecordAudio') return\n\n await useAudioService().registerWavEncoder()\n }\n})\n","import {\n type ComfyNodeDef,\n type InputSpec,\n isComboInputSpecV1\n} from '@/schemas/nodeDefSchema'\n\nimport { app } from '../../scripts/app'\n\n// Adds an upload button to the nodes\n\nconst isMediaUploadComboInput = (inputSpec: InputSpec) => {\n const [inputName, inputOptions] = inputSpec\n if (!inputOptions) return false\n\n const isUploadInput =\n inputOptions['image_upload'] === true ||\n inputOptions['video_upload'] === true ||\n inputOptions['animated_image_upload'] === true\n\n return (\n isUploadInput && (isComboInputSpecV1(inputSpec) || inputName === 'COMBO')\n )\n}\n\nconst createUploadInput = (\n imageInputName: string,\n imageInputOptions: InputSpec\n): InputSpec => [\n 'IMAGEUPLOAD',\n {\n ...imageInputOptions[1],\n imageInputName\n }\n]\n\napp.registerExtension({\n name: 'Comfy.UploadImage',\n beforeRegisterNodeDef(_nodeType, nodeData: ComfyNodeDef) {\n const { input } = nodeData ?? {}\n const { required } = input ?? {}\n if (!required) return\n\n const found = Object.entries(required).find(([_, input]) =>\n isMediaUploadComboInput(input)\n )\n\n // If media combo input found, attach upload input\n if (found) {\n const [inputName, inputSpec] = found\n required.upload = createUploadInput(inputName, inputSpec)\n }\n }\n})\n","import { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\n\nconst WEBCAM_READY = Symbol()\n\napp.registerExtension({\n name: 'Comfy.WebcamCapture',\n getCustomWidgets() {\n return {\n WEBCAM(node, inputName) {\n // @ts-expect-error fixme ts strict error\n let res\n // @ts-expect-error fixme ts strict error\n node[WEBCAM_READY] = new Promise((resolve) => (res = resolve))\n\n const container = document.createElement('div')\n container.style.background = 'rgba(0,0,0,0.25)'\n container.style.textAlign = 'center'\n\n const video = document.createElement('video')\n video.style.height = video.style.width = '100%'\n\n const loadVideo = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: false\n })\n container.replaceChildren(video)\n\n // @ts-expect-error fixme ts strict error\n setTimeout(() => res(video), 500) // Fallback as loadedmetadata doesnt fire sometimes?\n // @ts-expect-error fixme ts strict error\n video.addEventListener('loadedmetadata', () => res(video), false)\n video.srcObject = stream\n video.play()\n } catch (error) {\n const label = document.createElement('div')\n label.style.color = 'red'\n label.style.overflow = 'auto'\n label.style.maxHeight = '100%'\n label.style.whiteSpace = 'pre-wrap'\n\n if (window.isSecureContext) {\n label.textContent =\n 'Unable to load webcam, please ensure access is granted:\\n' +\n // @ts-expect-error fixme ts strict error\n error.message\n } else {\n label.textContent =\n 'Unable to load webcam. A secure context is required, if you are not accessing ComfyUI on localhost (127.0.0.1) you will have to enable TLS (https)\\n\\n' +\n // @ts-expect-error fixme ts strict error\n error.message\n }\n\n container.replaceChildren(label)\n }\n }\n\n loadVideo()\n\n return { widget: node.addDOMWidget(inputName, 'WEBCAM', container) }\n }\n }\n },\n nodeCreated(node) {\n if ((node.type, node.constructor.comfyClass !== 'WebcamCapture')) return\n\n // @ts-expect-error fixme ts strict error\n let video\n // @ts-expect-error fixme ts strict error\n const camera = node.widgets.find((w) => w.name === 'image')\n // @ts-expect-error fixme ts strict error\n const w = node.widgets.find((w) => w.name === 'width')\n // @ts-expect-error fixme ts strict error\n const h = node.widgets.find((w) => w.name === 'height')\n // @ts-expect-error fixme ts strict error\n const captureOnQueue = node.widgets.find(\n (w) => w.name === 'capture_on_queue'\n )\n\n const canvas = document.createElement('canvas')\n\n const capture = () => {\n // @ts-expect-error widget value type narrow down\n canvas.width = w.value\n // @ts-expect-error widget value type narrow down\n canvas.height = h.value\n const ctx = canvas.getContext('2d')\n // @ts-expect-error widget value type narrow down\n ctx.drawImage(video, 0, 0, w.value, h.value)\n const data = canvas.toDataURL('image/png')\n\n const img = new Image()\n img.onload = () => {\n node.imgs = [img]\n app.canvas.setDirty(true)\n }\n img.src = data\n }\n\n const btn = node.addWidget(\n 'button',\n 'waiting for camera...',\n 'capture',\n capture,\n { canvasOnly: true }\n )\n btn.disabled = true\n btn.serializeValue = () => undefined\n\n // @ts-expect-error fixme ts strict error\n camera.serializeValue = async () => {\n // @ts-expect-error fixme ts strict error\n if (captureOnQueue.value) {\n capture()\n } else if (!node.imgs?.length) {\n const err = `No webcam image captured`\n useToastStore().addAlert(err)\n throw new Error(err)\n }\n\n // Upload image to temp storage\n // @ts-expect-error fixme ts strict error\n const blob = await new Promise<Blob>((r) => canvas.toBlob(r))\n const name = `${+new Date()}.png`\n const file = new File([blob], name)\n const body = new FormData()\n body.append('image', file)\n body.append('subfolder', 'webcam')\n body.append('type', 'temp')\n const resp = await api.fetchApi('/upload/image', {\n method: 'POST',\n body\n })\n if (resp.status !== 200) {\n const err = `Error uploading camera image: ${resp.status} - ${resp.statusText}`\n useToastStore().addAlert(err)\n throw new Error(err)\n }\n return `webcam/${name} [temp]`\n }\n\n // @ts-expect-error fixme ts strict error\n node[WEBCAM_READY].then((v) => {\n video = v\n // If width isn't specified then use video output resolution\n // @ts-expect-error fixme ts strict error\n if (!w.value) {\n // @ts-expect-error fixme ts strict error\n w.value = video.videoWidth || 640\n // @ts-expect-error fixme ts strict error\n h.value = video.videoHeight || 480\n }\n btn.disabled = false\n btn.label = t('g.capture')\n })\n }\n})\n"],"names":["ClipspaceDialog","ComfyDialog","__name","name","contextPredicate","callback","item","$el","ComfyApp","img_preview","self","children","buttons","idx","combo_items","imgs","i","combo1","event","row1","combo2","row2","td","row3","app","ext","ctxMenu","LiteGraph","values","options","ctx","filter","items","displayedItems","itemCount","clickedComboValue","LGraphCanvas","w","isComboWidget","v","selectedIndex","selectedItem","updateSelected","positionList","scale","shift","term","isVisible","d","top","bodyRect","rootRect","applyToGraph","extraLinks","links","l","linkInfo","node","input","widgetName","widget","onNodeCreated","useChainCallback","comboWidget","shallowReactive","updateCombo","addOption","newCount","value","lastWidget","nodeType","nodeData","useExtensionService","widgets","workflowNode","widgetIndex","prompt","processDynamicPrompt","editAttentionDelta","incrementWeight","weight","delta","floatWeight","newWeight","findNearestEnclosure","text","cursorPos","start","end","openCount","closeCount","addWeightToParentheses","parenRegex","parenMatch","floatRegex","floatMatch","editAttention","inputField","selectedText","nearestEnclosure","delimiters","weightDelta","updatedText","_","PYTHON_MIRROR","checkMirrorReachable","mirror","isValidUrl","electronAPI","isElectron","getElectronAPI","desktopAppVersion","workflowStore","useWorkflowStore","toastStore","useToastStore","staticUrls","buildDocsUrl","useExternalLink","onChangeRestartApp","newValue","oldValue","updateInfo","t","useDialogService","error","log","ExecutableGroupNodeChildDTO","ExecutableNodeDTO","subgraphNodePath","nodesByExecutionId","subgraphNode","groupNodeHandler","slot","inputNode","link","inputNodeId","inputNodeDto","id","ORDER","merge","target","source","key","sv","tv","ManageGroupDialog","tab","index","force","PREFIX","SEPARATOR","GroupNodeHandler","group","reset","nodes","n","ordered","DraggableList","oldPosition","newPosition","props","nodeIndex","section","prop","groupMod","nodesMod","nodeMod","typeMod","objMod","placeholder","checked","checkable","mods","e","config","oldName","inputs","innerNodeDef","outputs","groupOutputs","type","groupOutputIndex","visible","groupNodes","a","b","pages","p","page","outer","g","nodesByType","recreateNodes","types","nodeMods","keys","orderedNodes","orderedMods","orderedConfig","order","GroupNodeConfig","IGNORE_KEYS","getRange","min","max","mergeNumericInputSpec","spec1","spec2","options1","options2","range1","range2","step1","step2","mergedOptions","lcm","mergeCommonInputSpec","mergeComboInputSpec","comboOptions1","getComboSpecComboOptions","comboOptions2","intersection","getInputSpecType","value1","value2","mergeInputSpec","type1","type2","isIntInputSpec","isFloatInputSpec","isComboInputSpec","isPrimitiveNode","replacePropertyName","PrimitiveNode","LGraphNode","title","applyTextReplacements","GET_CONFIG","#onFirstConnection","#mergeWidgetConfig","_type","_index","connected","target_node","target_slot","ComfyWidgets","valid","#isValidConnection","recreating","linkId","theirNode","getWidgetType","#createWidget","CONFIG","inputData","oldWidth","oldHeight","isValidWidgetType","theirWidget","control_value","addValueControlWidgets","controlValues","sz","#removeWidgets","output","hasConfig","config1","theirInput","forceUpdate","config2","mergeIfValid","getWidgetConfig","getConfig","convertToInput","setWidgetConfig","NodeSlot","graph","originNode","recreateWidget","customSpec","_nodeData","origOnInputDblClick","args","pos","Workflow","data","extra","GroupNodeBuilder","nodesInOrder","storeLinkTypes","storeExternalLinks","hasExternal","serialised","serialise","GROUP","seenInputs","seenOutputs","#convertedToProcess","useNodeDefStore","sourceNodeId","sourceNodeSlot","targetNodeId","targetNodeSlot","def","globalDefs","linksFrom","fromTypeName","fromType","linksTo","rerouteType","targetDef","targetWidget","inputName","customConfig","inp","prefix","inputNames","slots","converted","widgetMap","useWidgetStore","convertedIndex","__","primitiveDef","primitiveConfig","toPrimitive","toWidget","inputMap","convertedSlots","k","inputMapping","oldToNew","outputId","hasLink","label","o","missingNodeTypes","groupData","hasMissing","innerNodes","innerNodeIndex","innerNode","externalSlot","innerLink","computedNodeDtos","visited","subgraphInstanceIdPath","currentId","aVeryRealNode","groupNode","addInnerNodes","c","ids","deserialiseAndCreate","x","y","left","selectedIds","newNodes","newNode","map","newName","outerWidget","newWidget","reconnectInputs","innerInputId","groupSlotId","reconnectOutputs","groupOutputId","targetNode","getExtraMenuOptions","optionIndex","manageGroupNodes","onDrawTitleBox","height","fill","onDrawForeground","progressState","useExecutionStore","message","onExecutionStart","handleEvent","getId","getEvent","handler","detail","api","executing","executed","onRemoved","defs","old","newWidgetName","primitiveLinked","linked","rerouteLinks","targetSlot","_node","nodeId","primitiveId","targetWidgetName","targetWidgetIndex","primitiveNode","len","offset","linkedShift","mainWidget","innerWidget","originalNode","newSlot","originSlot","targetId","actualOriginId","builder","res","replaceLegacySeparators","convertSelectedNodesToGroupNode","SubgraphNode","convertDisabled","selected","ungroupSelectedGroupNodes","canvas","convertEnabled","groups","manageDisabled","graphData","setNodeMode","mode","addNodesToGroup","padding","useSettingStore","LGraphGroup","nodesInGroup","allNodesAreSameMode","onExecuted","aImages","bImages","rand","beforeUrl","afterUrl","EXPORT_FORMATS","createExportMenuItems","load3d","_value","_options","prev_menu","submenuOptions","format","Load3DConfiguration","properties","loadFolder","filePath","setting","width","onModelWidgetUpdate","modelWidget","cameraState","originalCallback","currentValue","bgImagePath","sceneConfig","cameraConfig","lightConfig","isFirstLoad","filename","modelUrl","Load3dUtils","modelConfig","pathParts","part","subfolder","inputSpecLoad3D","inputSpecPreview3D","handleModelUpload","files","resourceFolder","uploadPath","useLoad3d","handleResourcesUpload","createFileInput","accept","multiple","selectedNodes","selectedNode","isLoad3dNode","useDialogStore","Load3DViewerContent","useLoad3dService","fileInput","resourcesInput","ComponentWidgetImpl","Load3D","addWidget","nextTick","sceneWidget","settings","currentLoad3d","nodeToLoad3dMap","imageData","maskData","normalData","dataMask","dataNormal","returnVal","recordingData","recording","_nodeType","lastTimeModelFile","msg","openMaskEditor","useMaskEditor","openMaskEditorFromClipspace","isOpened","changeBrushSize","sizeChanger","store","useMaskEditorStore","oldBrushSize","newBrushSize","file","ManageTemplates","btns","templates","reader","importFile","template","json","blob","downloadBlob","nameInput","el","prev_i","rect","row","that","manage","clipboardAction","cb","_canvas","nodeIds","subItems","NoteNode","MarkdownNoteNode","showValueWidget","showValueWidgetPlain","showAsPlaintextWidget","previewWidgets","previewWidget","RerouteNode","cloned","linksToDisconnect","currentNode","updateNodes","inputType","outputType","nodeInput","nodeOutType","keep","displayType","color","widgetConfig","widgetType","targetInput","merged","saveNodeTypes","r","inputSpec","fileInfo","drawSelectionBorder","selectedItems","bounds","createBounds","borderWidth","dashSize","originalDrawForeground","visibleArea","touchZooming","touchCount","touchDist","touchTime","lastTouch","lastScale","getMultiTouchPos","getMultiTouchCenter","touch","resetTouchState","onlyTouch","deltaX","deltaY","newTouchDist","center","newX","newY","oldScale","newScale","convertScaleToOffset","oldCenter","newCenter","processMouseDown","processMouseMove","newVal","inputKey","customProperties","lowerType","maxNum","uploadFile","audioWidget","audioUIWidget","updateNode","pasted","body","resp","path","getResourceURL","splitFilePath","audio","audios","nodeOutputs","nodeLocatorId","getNodeByLocatorId","onAudioWidgetUpdate","onGraphConfigured","handleUpload","isAudioFile","openFileSelection","useNodeFileInput","uploadWidget","useNodeDragAndDrop","useNodePaste","mediaRecorder","isRecording","audioChunks","currentStream","recordWidget","stopPromise","stopResolve","resolve","audioSrc","useAudioService","ExtendableMediaRecorder","audioBlob","err","originalOnRemoved","isMediaUploadComboInput","inputOptions","isComboInputSpecV1","createUploadInput","imageInputName","imageInputOptions","required","found","WEBCAM_READY","container","video","stream","camera","h","captureOnQueue","capture","img","btn"],"mappings":"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"}
1
+ {"version":3,"file":"index-KizWjI6s.js","sources":["../../src/extensions/core/clipspace.ts","../../src/extensions/core/contextMenuFilter.ts","../../src/extensions/core/customCombo.ts","../../src/extensions/core/dynamicPrompts.ts","../../src/extensions/core/editAttention.ts","../../src/constants/uvMirrors.ts","../../src/utils/electronMirrorCheck.ts","../../src/extensions/core/electronAdapter.ts","../../src/utils/executableGroupNodeChildDTO.ts","../../src/extensions/core/groupNodeManage.ts","../../src/utils/nodeDefUtil.ts","../../src/renderer/utils/nodeTypeGuards.ts","../../src/extensions/core/widgetInputs.ts","../../src/extensions/core/groupNode.ts","../../src/extensions/core/groupOptions.ts","../../src/extensions/core/imageCompare.ts","../../src/extensions/core/load3d/exportMenuHelper.ts","../../src/extensions/core/load3d/Load3DConfiguration.ts","../../src/extensions/core/load3d.ts","../../src/extensions/core/maskeditor.ts","../../src/extensions/core/nodeTemplates.ts","../../src/extensions/core/noteNode.ts","../../src/extensions/core/previewAny.ts","../../src/extensions/core/rerouteNode.ts","../../src/extensions/core/saveImageExtraOutput.ts","../../src/extensions/core/saveMesh.ts","../../src/extensions/core/selectionBorder.ts","../../src/extensions/core/simpleTouchSupport.ts","../../src/extensions/core/slotDefaults.ts","../../src/extensions/core/uploadAudio.ts","../../src/extensions/core/uploadImage.ts","../../src/extensions/core/webcamCapture.ts"],"sourcesContent":["import { app } from '../../scripts/app'\nimport { ComfyApp } from '../../scripts/app'\nimport { $el, ComfyDialog } from '../../scripts/ui'\n\nexport class ClipspaceDialog extends ComfyDialog {\n static items: Array<\n HTMLButtonElement & {\n contextPredicate?: () => boolean\n }\n > = []\n static instance: ClipspaceDialog | null = null\n\n static registerButton(\n name: string,\n contextPredicate: () => boolean,\n callback: () => void\n ) {\n const item = $el('button', {\n type: 'button',\n textContent: name,\n contextPredicate: contextPredicate,\n onclick: callback\n })\n\n ClipspaceDialog.items.push(item)\n }\n\n static invalidatePreview() {\n if (\n ComfyApp.clipspace &&\n ComfyApp.clipspace.imgs &&\n ComfyApp.clipspace.imgs.length > 0\n ) {\n const img_preview = document.getElementById(\n 'clipspace_preview'\n ) as HTMLImageElement\n if (img_preview) {\n img_preview.src =\n ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src\n img_preview.style.maxHeight = '100%'\n img_preview.style.maxWidth = '100%'\n }\n }\n }\n\n static invalidate() {\n if (ClipspaceDialog.instance) {\n const self = ClipspaceDialog.instance\n // allow reconstruct controls when copying from non-image to image content.\n const children = $el('div.comfy-modal-content', [\n self.createImgSettings(),\n ...self.createButtons()\n ])\n\n if (self.element) {\n // update\n if (self.element.firstChild) {\n self.element.removeChild(self.element.firstChild)\n }\n self.element.appendChild(children)\n } else {\n // new\n self.element = $el('div.comfy-modal', { parent: document.body }, [\n children\n ])\n }\n\n if (self.element.children[0].children.length <= 1) {\n self.element.children[0].appendChild(\n $el('p', {}, [\n 'Unable to find the features to edit content of a format stored in the current Clipspace.'\n ])\n )\n }\n\n ClipspaceDialog.invalidatePreview()\n }\n }\n\n constructor() {\n super()\n }\n\n override createButtons() {\n const buttons = []\n\n for (let idx in ClipspaceDialog.items) {\n const item = ClipspaceDialog.items[idx]\n if (!item.contextPredicate || item.contextPredicate())\n buttons.push(ClipspaceDialog.items[idx])\n }\n\n buttons.push(\n $el('button', {\n type: 'button',\n textContent: 'Close',\n onclick: () => {\n this.close()\n }\n })\n )\n\n return buttons\n }\n\n createImgSettings() {\n if (ComfyApp.clipspace?.imgs) {\n const combo_items = []\n const imgs = ComfyApp.clipspace.imgs\n\n for (let i = 0; i < imgs.length; i++) {\n combo_items.push($el('option', { value: i }, [`${i}`]))\n }\n\n const combo1 = $el(\n 'select',\n {\n id: 'clipspace_img_selector',\n onchange: (event: Event) => {\n if (event.target && ComfyApp.clipspace) {\n ComfyApp.clipspace['selectedIndex'] = (\n event.target as HTMLSelectElement\n ).selectedIndex\n ClipspaceDialog.invalidatePreview()\n }\n }\n },\n combo_items\n )\n\n const row1 = $el('tr', {}, [\n $el('td', {}, [$el('font', { color: 'white' }, ['Select Image'])]),\n $el('td', {}, [combo1])\n ])\n\n const combo2 = $el(\n 'select',\n {\n id: 'clipspace_img_paste_mode',\n onchange: (event: Event) => {\n if (event.target && ComfyApp.clipspace) {\n ComfyApp.clipspace['img_paste_mode'] = (\n event.target as HTMLSelectElement\n ).value\n }\n }\n },\n [\n $el('option', { value: 'selected' }, 'selected'),\n $el('option', { value: 'all' }, 'all')\n ]\n ) as HTMLSelectElement\n combo2.value = ComfyApp.clipspace['img_paste_mode']\n\n const row2 = $el('tr', {}, [\n $el('td', {}, [$el('font', { color: 'white' }, ['Paste Mode'])]),\n $el('td', {}, [combo2])\n ])\n\n const td = $el(\n 'td',\n { align: 'center', width: '100px', height: '100px', colSpan: '2' },\n [$el('img', { id: 'clipspace_preview', ondragstart: () => false }, [])]\n )\n\n const row3 = $el('tr', {}, [td])\n\n return $el('table', {}, [row1, row2, row3])\n } else {\n return []\n }\n }\n\n createImgPreview() {\n if (ComfyApp.clipspace?.imgs) {\n return $el('img', { id: 'clipspace_preview', ondragstart: () => false })\n } else return []\n }\n\n override show() {\n ClipspaceDialog.invalidate()\n\n this.element.style.display = 'block'\n }\n}\n\napp.registerExtension({\n name: 'Comfy.Clipspace',\n init(app) {\n app.openClipspace = function () {\n if (!ClipspaceDialog.instance) {\n ClipspaceDialog.instance = new ClipspaceDialog()\n ComfyApp.clipspace_invalidate_handler = ClipspaceDialog.invalidate\n }\n\n if (ComfyApp.clipspace) {\n ClipspaceDialog.instance.show()\n } else app.ui.dialog.show('Clipspace is Empty!')\n }\n }\n})\n","import {\n LGraphCanvas,\n LiteGraph,\n isComboWidget\n} from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '../../scripts/app'\n\n// Adds filtering to combo context menus\n\nconst ext = {\n name: 'Comfy.ContextMenuFilter',\n init() {\n const ctxMenu = LiteGraph.ContextMenu\n\n // @ts-expect-error TODO Very hacky way to modify Litegraph behaviour. Fix ctx later.\n LiteGraph.ContextMenu = function (values, options) {\n const ctx = new ctxMenu(values, options)\n\n // If we are a dark menu (only used for combo boxes) then add a filter input\n if (options?.className === 'dark' && values?.length > 4) {\n const filter = document.createElement('input')\n filter.classList.add('comfy-context-menu-filter')\n filter.placeholder = 'Filter list'\n\n ctx.root.prepend(filter)\n\n const items = Array.from(\n ctx.root.querySelectorAll('.litemenu-entry')\n ) as HTMLElement[]\n let displayedItems = [...items]\n let itemCount = displayedItems.length\n\n // We must request an animation frame for the current node of the active canvas to update.\n requestAnimationFrame(() => {\n const currentNode = LGraphCanvas.active_canvas.current_node\n const clickedComboValue = currentNode?.widgets\n ?.filter(\n (w) =>\n isComboWidget(w) && w.options.values?.length === values.length\n )\n .find((w) =>\n // @ts-expect-error Poorly typed; filter above \"should\" mitigate exceptions\n w.options.values?.every((v, i) => v === values[i])\n )?.value\n\n let selectedIndex = clickedComboValue\n ? values.findIndex((v: string) => v === clickedComboValue)\n : 0\n if (selectedIndex < 0) {\n selectedIndex = 0\n }\n let selectedItem = displayedItems[selectedIndex]\n updateSelected()\n\n // Apply highlighting to the selected item\n function updateSelected() {\n selectedItem?.style.setProperty('background-color', '')\n selectedItem?.style.setProperty('color', '')\n selectedItem = displayedItems[selectedIndex]\n selectedItem?.style.setProperty(\n 'background-color',\n '#ccc',\n 'important'\n )\n selectedItem?.style.setProperty('color', '#000', 'important')\n }\n\n const positionList = () => {\n const rect = ctx.root.getBoundingClientRect()\n\n // If the top is off-screen then shift the element with scaling applied\n if (rect.top < 0) {\n const scale =\n 1 -\n ctx.root.getBoundingClientRect().height / ctx.root.clientHeight\n\n const shift = (ctx.root.clientHeight * scale) / 2\n\n ctx.root.style.top = -shift + 'px'\n }\n }\n\n // Arrow up/down to select items\n filter.addEventListener('keydown', (event) => {\n switch (event.key) {\n case 'ArrowUp':\n event.preventDefault()\n if (selectedIndex === 0) {\n selectedIndex = itemCount - 1\n } else {\n selectedIndex--\n }\n updateSelected()\n break\n case 'ArrowRight':\n event.preventDefault()\n selectedIndex = itemCount - 1\n updateSelected()\n break\n case 'ArrowDown':\n event.preventDefault()\n if (selectedIndex === itemCount - 1) {\n selectedIndex = 0\n } else {\n selectedIndex++\n }\n updateSelected()\n break\n case 'ArrowLeft':\n event.preventDefault()\n selectedIndex = 0\n updateSelected()\n break\n case 'Enter':\n selectedItem?.click()\n break\n case 'Escape':\n ctx.close()\n break\n }\n })\n\n filter.addEventListener('input', () => {\n // Hide all items that don't match our filter\n const term = filter.value.toLocaleLowerCase()\n // When filtering, recompute which items are visible for arrow up/down and maintain selection.\n displayedItems = items.filter((item) => {\n const isVisible =\n !term || item.textContent?.toLocaleLowerCase().includes(term)\n item.style.display = isVisible ? 'block' : 'none'\n return isVisible\n })\n\n selectedIndex = 0\n if (displayedItems.includes(selectedItem)) {\n selectedIndex = displayedItems.findIndex(\n (d) => d === selectedItem\n )\n }\n itemCount = displayedItems.length\n\n updateSelected()\n\n // If we have an event then we can try and position the list under the source\n if (options.event) {\n let top = options.event.clientY - 10\n\n const bodyRect = document.body.getBoundingClientRect()\n\n const rootRect = ctx.root.getBoundingClientRect()\n if (\n bodyRect.height &&\n top > bodyRect.height - rootRect.height - 10\n ) {\n top = Math.max(0, bodyRect.height - rootRect.height - 10)\n }\n\n ctx.root.style.top = top + 'px'\n positionList()\n }\n })\n\n requestAnimationFrame(() => {\n // Focus the filter box when opening\n filter.focus()\n\n positionList()\n })\n })\n }\n\n return ctx\n }\n\n LiteGraph.ContextMenu.prototype = ctxMenu.prototype\n }\n}\n\napp.registerExtension(ext)\n","import { shallowReactive } from 'vue'\n\nimport { useChainCallback } from '@/composables/functional/useChainCallback'\nimport type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'\nimport { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport { LLink } from '@/lib/litegraph/src/litegraph'\nimport { app } from '@/scripts/app'\n\nfunction applyToGraph(this: LGraphNode, extraLinks: LLink[] = []) {\n if (!this.outputs[0].links?.length || !this.graph) return\n\n const links = [\n ...this.outputs[0].links.map((l) => this.graph!.links[l]),\n ...extraLinks\n ]\n let v = this.widgets?.[0].value\n // For each output link copy our value over the original widget value\n for (const linkInfo of links) {\n const node = this.graph?.getNodeById(linkInfo.target_id)\n const input = node?.inputs[linkInfo.target_slot]\n if (!input) {\n console.warn('Unable to resolve node or input for link', linkInfo)\n continue\n }\n\n const widgetName = input.widget?.name\n if (!widgetName) {\n console.warn('Invalid widget or widget name', input.widget)\n continue\n }\n\n const widget = node.widgets?.find((w) => w.name === widgetName)\n if (!widget) {\n console.warn(`Unable to find widget \"${widgetName}\" on node [${node.id}]`)\n continue\n }\n\n widget.value = v\n widget.callback?.(\n widget.value,\n app.canvas,\n node,\n app.canvas.graph_mouse,\n {} as CanvasPointerEvent\n )\n }\n}\n\nfunction onNodeCreated(this: LGraphNode) {\n this.applyToGraph = useChainCallback(this.applyToGraph, applyToGraph)\n\n const comboWidget = this.widgets![0]\n const values = shallowReactive<string[]>([])\n comboWidget.options.values = values\n\n const updateCombo = () => {\n values.splice(\n 0,\n values.length,\n ...this.widgets!.filter(\n (w) => w.name.startsWith('option') && w.value\n ).map((w) => `${w.value}`)\n )\n if (app.configuringGraph) return\n if (values.includes(`${comboWidget.value}`)) return\n comboWidget.value = values[0] ?? ''\n comboWidget.callback?.(comboWidget.value)\n }\n comboWidget.callback = useChainCallback(comboWidget.callback, () =>\n this.applyToGraph!()\n )\n\n function addOption(node: LGraphNode) {\n if (!node.widgets) return\n const newCount = node.widgets.length - 1\n node.addWidget('string', `option${newCount}`, '', () => {})\n const widget = node.widgets.at(-1)\n if (!widget) return\n\n let value = ''\n Object.defineProperty(widget, 'value', {\n get() {\n return value\n },\n set(v) {\n value = v\n updateCombo()\n if (!node.widgets) return\n const lastWidget = node.widgets.at(-1)\n if (lastWidget === this) {\n if (v) addOption(node)\n return\n }\n if (v || node.widgets.at(-2) !== this || lastWidget?.value) return\n node.widgets.pop()\n node.computeSize(node.size)\n this.callback(v)\n }\n })\n }\n addOption(this)\n}\n\napp.registerExtension({\n name: 'Comfy.CustomCombo',\n beforeRegisterNodeDef(nodeType, nodeData) {\n if (nodeData?.name !== 'CustomCombo') return\n nodeType.prototype.onNodeCreated = useChainCallback(\n nodeType.prototype.onNodeCreated,\n onNodeCreated\n )\n }\n})\n","import { useExtensionService } from '@/services/extensionService'\nimport { processDynamicPrompt } from '@/utils/formatUtil'\n\n// Allows for simple dynamic prompt replacement\n// Inputs in the format {a|b} will have a random value of a or b chosen when the prompt is queued.\n\nuseExtensionService().registerExtension({\n name: 'Comfy.DynamicPrompts',\n nodeCreated(node) {\n if (node.widgets) {\n // Locate dynamic prompt text widgets\n // Include any widgets with dynamicPrompts set to true, and customtext\n const widgets = node.widgets.filter((w) => w.dynamicPrompts)\n for (const widget of widgets) {\n // Override the serialization of the value to resolve dynamic prompts for all widgets supporting it in this node\n widget.serializeValue = (workflowNode, widgetIndex) => {\n if (typeof widget.value !== 'string') return widget.value\n\n const prompt = processDynamicPrompt(widget.value)\n\n // Overwrite the value in the serialized workflow pnginfo\n if (workflowNode?.widgets_values)\n workflowNode.widgets_values[widgetIndex] = prompt\n\n return prompt\n }\n }\n }\n }\n})\n","import { app } from '../../scripts/app'\n\n// Allows you to edit the attention weight by holding ctrl (or cmd) and using the up/down arrow keys\n\napp.registerExtension({\n name: 'Comfy.EditAttention',\n init() {\n const editAttentionDelta = app.ui.settings.addSetting({\n id: 'Comfy.EditAttention.Delta',\n category: ['Comfy', 'EditTokenWeight', 'Delta'],\n name: 'Ctrl+up/down precision',\n type: 'slider',\n attrs: {\n min: 0.01,\n max: 0.5,\n step: 0.01\n },\n defaultValue: 0.05\n })\n\n function incrementWeight(weight: string, delta: number): string {\n const floatWeight = parseFloat(weight)\n if (isNaN(floatWeight)) return weight\n const newWeight = floatWeight + delta\n return String(Number(newWeight.toFixed(10)))\n }\n\n type Enclosure = {\n start: number\n end: number\n }\n\n function findNearestEnclosure(\n text: string,\n cursorPos: number\n ): Enclosure | null {\n let start = cursorPos,\n end = cursorPos\n let openCount = 0,\n closeCount = 0\n\n // Find opening parenthesis before cursor\n while (start >= 0) {\n start--\n if (text[start] === '(' && openCount === closeCount) break\n if (text[start] === '(') openCount++\n if (text[start] === ')') closeCount++\n }\n if (start < 0) return null\n\n openCount = 0\n closeCount = 0\n\n // Find closing parenthesis after cursor\n while (end < text.length) {\n if (text[end] === ')' && openCount === closeCount) break\n if (text[end] === '(') openCount++\n if (text[end] === ')') closeCount++\n end++\n }\n if (end === text.length) return null\n\n return { start: start + 1, end: end }\n }\n\n function addWeightToParentheses(text: string): string {\n const parenRegex = /^\\((.*)\\)$/\n const parenMatch = text.match(parenRegex)\n\n const floatRegex = /:([+-]?(\\d*\\.)?\\d+([eE][+-]?\\d+)?)/\n const floatMatch = text.match(floatRegex)\n\n if (parenMatch && !floatMatch) {\n return `(${parenMatch[1]}:1.0)`\n } else {\n return text\n }\n }\n\n function editAttention(event: KeyboardEvent) {\n // @ts-expect-error Runtime narrowing not impl.\n const inputField: HTMLTextAreaElement = event.composedPath()[0]\n const delta = parseFloat(editAttentionDelta.value)\n\n if (inputField.tagName !== 'TEXTAREA') return\n if (!(event.key === 'ArrowUp' || event.key === 'ArrowDown')) return\n if (!event.ctrlKey && !event.metaKey) return\n\n event.preventDefault()\n\n let start = inputField.selectionStart\n let end = inputField.selectionEnd\n let selectedText = inputField.value.substring(start, end)\n\n // If there is no selection, attempt to find the nearest enclosure, or select the current word\n if (!selectedText) {\n const nearestEnclosure = findNearestEnclosure(inputField.value, start)\n if (nearestEnclosure) {\n start = nearestEnclosure.start\n end = nearestEnclosure.end\n selectedText = inputField.value.substring(start, end)\n } else {\n // Select the current word, find the start and end of the word\n const delimiters = ' .,\\\\/!?%^*;:{}=-_`~()\\r\\n\\t'\n\n while (\n !delimiters.includes(inputField.value[start - 1]) &&\n start > 0\n ) {\n start--\n }\n\n while (\n !delimiters.includes(inputField.value[end]) &&\n end < inputField.value.length\n ) {\n end++\n }\n\n selectedText = inputField.value.substring(start, end)\n if (!selectedText) return\n }\n }\n\n // If the selection ends with a space, remove it\n if (selectedText[selectedText.length - 1] === ' ') {\n selectedText = selectedText.substring(0, selectedText.length - 1)\n end -= 1\n }\n\n // If there are parentheses left and right of the selection, select them\n if (\n inputField.value[start - 1] === '(' &&\n inputField.value[end] === ')'\n ) {\n start -= 1\n end += 1\n selectedText = inputField.value.substring(start, end)\n }\n\n // If the selection is not enclosed in parentheses, add them\n if (\n selectedText[0] !== '(' ||\n selectedText[selectedText.length - 1] !== ')'\n ) {\n selectedText = `(${selectedText})`\n }\n\n // If the selection does not have a weight, add a weight of 1.0\n selectedText = addWeightToParentheses(selectedText)\n\n // Increment the weight\n const weightDelta = event.key === 'ArrowUp' ? delta : -delta\n const updatedText = selectedText.replace(\n /\\((.*):([+-]?\\d+(?:\\.\\d+)?)\\)/,\n (_, text, weight) => {\n weight = incrementWeight(weight, weightDelta)\n if (weight == 1) {\n return text\n } else {\n return `(${text}:${weight})`\n }\n }\n )\n\n inputField.setSelectionRange(start, end)\n // Intentional use of deprecated: https://developer.mozilla.org/docs/Web/API/Document/execCommand#using_inserttext\n document.execCommand('insertText', false, updatedText)\n inputField.setSelectionRange(start, start + updatedText.length)\n }\n window.addEventListener('keydown', editAttention)\n }\n})\n","interface UVMirror {\n /**\n * The setting id defined for the mirror.\n */\n settingId: string\n /**\n * The default mirror to use.\n */\n mirror: string\n /**\n * The fallback mirror to use.\n */\n fallbackMirror: string\n /**\n * The path suffix to validate the mirror is reachable.\n */\n validationPathSuffix?: string\n}\n\nexport const PYTHON_MIRROR: UVMirror = {\n settingId: 'Comfy-Desktop.UV.PythonInstallMirror',\n mirror:\n 'https://github.com/astral-sh/python-build-standalone/releases/download',\n fallbackMirror:\n 'https://python-standalone.org/mirror/astral-sh/python-build-standalone',\n validationPathSuffix:\n '/20250115/cpython-3.10.16+20250115-aarch64-apple-darwin-debug-full.tar.zst.sha256'\n}\n","import { electronAPI } from '@/utils/envUtil'\nimport { isValidUrl } from '@/utils/formatUtil'\n\n/**\n * Check if a mirror is reachable from the electron App.\n * @param mirror - The mirror to check.\n * @returns True if the mirror is reachable, false otherwise.\n */\nexport const checkMirrorReachable = async (mirror: string) => {\n return (\n isValidUrl(mirror) && (await electronAPI().NetWork.canAccessUrl(mirror))\n )\n}\n","import log from 'loglevel'\n\nimport { useExternalLink } from '@/composables/useExternalLink'\nimport { PYTHON_MIRROR } from '@/constants/uvMirrors'\nimport { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'\nimport { app } from '@/scripts/app'\nimport { useDialogService } from '@/services/dialogService'\nimport { checkMirrorReachable } from '@/utils/electronMirrorCheck'\nimport { electronAPI as getElectronAPI, isElectron } from '@/utils/envUtil'\n;(async () => {\n if (!isElectron()) return\n\n const electronAPI = getElectronAPI()\n const desktopAppVersion = await electronAPI.getElectronVersion()\n const workflowStore = useWorkflowStore()\n const toastStore = useToastStore()\n const { staticUrls, buildDocsUrl } = useExternalLink()\n\n const onChangeRestartApp = (newValue: string, oldValue: string) => {\n // Add a delay to allow changes to take effect before restarting.\n if (oldValue !== undefined && newValue !== oldValue) {\n electronAPI.restartApp('Restart ComfyUI to apply changes.', 1500)\n }\n }\n\n app.registerExtension({\n name: 'Comfy.ElectronAdapter',\n settings: [\n {\n id: 'Comfy-Desktop.AutoUpdate',\n category: ['Comfy-Desktop', 'General', 'AutoUpdate'],\n name: 'Automatically check for updates',\n type: 'boolean',\n defaultValue: true,\n onChange: onChangeRestartApp\n },\n {\n id: 'Comfy-Desktop.SendStatistics',\n category: ['Comfy-Desktop', 'General', 'Send Statistics'],\n name: 'Send anonymous usage metrics',\n type: 'boolean',\n defaultValue: true,\n onChange: onChangeRestartApp\n },\n {\n id: 'Comfy-Desktop.WindowStyle',\n category: ['Comfy-Desktop', 'General', 'Window Style'],\n name: 'Window Style',\n tooltip: \"Custom: Replace the system title bar with ComfyUI's Top menu\",\n type: 'combo',\n experimental: true,\n defaultValue: 'default',\n options: ['default', 'custom'],\n onChange: (\n newValue: 'default' | 'custom',\n oldValue?: 'default' | 'custom'\n ) => {\n if (!oldValue) return\n\n electronAPI.Config.setWindowStyle(newValue)\n }\n },\n {\n id: 'Comfy-Desktop.UV.PythonInstallMirror',\n name: 'Python Install Mirror',\n tooltip: `Managed Python installations are downloaded from the Astral python-build-standalone project. This variable can be set to a mirror URL to use a different source for Python installations. The provided URL will replace https://github.com/astral-sh/python-build-standalone/releases/download in, e.g., https://github.com/astral-sh/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz. Distributions can be read from a local directory by using the file:// URL scheme.`,\n type: 'url',\n defaultValue: '',\n attrs: {\n validateUrlFn(mirror: string) {\n return checkMirrorReachable(\n mirror + PYTHON_MIRROR.validationPathSuffix\n )\n }\n }\n },\n {\n id: 'Comfy-Desktop.UV.PypiInstallMirror',\n name: 'Pypi Install Mirror',\n tooltip: `Default pip install mirror`,\n type: 'url',\n defaultValue: '',\n attrs: {\n validateUrlFn: checkMirrorReachable\n }\n },\n {\n id: 'Comfy-Desktop.UV.TorchInstallMirror',\n name: 'Torch Install Mirror',\n tooltip: `Pip install mirror for pytorch`,\n type: 'url',\n defaultValue: '',\n attrs: {\n validateUrlFn: checkMirrorReachable\n }\n }\n ],\n\n commands: [\n {\n id: 'Comfy-Desktop.Folders.OpenLogsFolder',\n label: 'Open Logs Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openLogsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenModelsFolder',\n label: 'Open Models Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openModelsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenOutputsFolder',\n label: 'Open Outputs Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openOutputsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenInputsFolder',\n label: 'Open Inputs Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openInputsFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenCustomNodesFolder',\n label: 'Open Custom Nodes Folder',\n icon: 'pi pi-folder-open',\n function() {\n electronAPI.openCustomNodesFolder()\n }\n },\n {\n id: 'Comfy-Desktop.Folders.OpenModelConfig',\n label: 'Open extra_model_paths.yaml',\n icon: 'pi pi-file',\n function() {\n electronAPI.openModelConfig()\n }\n },\n {\n id: 'Comfy-Desktop.OpenDevTools',\n label: 'Open DevTools',\n icon: 'pi pi-code',\n function() {\n electronAPI.openDevTools()\n }\n },\n {\n id: 'Comfy-Desktop.OpenUserGuide',\n label: 'Desktop User Guide',\n icon: 'pi pi-book',\n function() {\n window.open(\n buildDocsUrl('/installation/desktop', {\n includeLocale: true,\n platform: true\n }),\n '_blank'\n )\n }\n },\n {\n id: 'Comfy-Desktop.CheckForUpdates',\n label: 'Check for Updates',\n icon: 'pi pi-sync',\n async function() {\n try {\n const updateInfo = await electronAPI.checkForUpdates({\n disableUpdateReadyAction: true\n })\n\n if (!updateInfo.isUpdateAvailable) {\n toastStore.add({\n severity: 'info',\n summary: t('desktopUpdate.noUpdateFound'),\n life: 5_000\n })\n return\n }\n\n const proceed = await useDialogService().confirm({\n title: t('desktopUpdate.updateFoundTitle', {\n version: updateInfo.version\n }),\n message: t('desktopUpdate.updateAvailableMessage'),\n type: 'default'\n })\n if (proceed) {\n try {\n electronAPI.restartAndInstall()\n } catch (error) {\n log.error('Error installing update:', error)\n toastStore.add({\n severity: 'error',\n summary: t('g.error'),\n detail: t('desktopUpdate.errorInstallingUpdate'),\n life: 10_000\n })\n }\n }\n } catch (error) {\n log.error('Error checking for updates:', error)\n toastStore.add({\n severity: 'error',\n summary: t('g.error'),\n detail: t('desktopUpdate.errorCheckingUpdate'),\n life: 10_000\n })\n }\n }\n },\n {\n id: 'Comfy-Desktop.Reinstall',\n label: 'Reinstall',\n icon: 'pi pi-refresh',\n async function() {\n const proceed = await useDialogService().confirm({\n message: t('desktopMenu.confirmReinstall'),\n title: t('desktopMenu.reinstall'),\n type: 'reinstall'\n })\n\n if (proceed) electronAPI.reinstall()\n }\n },\n {\n id: 'Comfy-Desktop.Restart',\n label: 'Restart',\n icon: 'pi pi-refresh',\n function() {\n electronAPI.restartApp()\n }\n },\n {\n id: 'Comfy-Desktop.Quit',\n label: 'Quit',\n icon: 'pi pi-sign-out',\n async function() {\n // Confirm if unsaved workflows are open\n if (workflowStore.modifiedWorkflows.length > 0) {\n const confirmed = await useDialogService().confirm({\n message: t('desktopMenu.confirmQuit'),\n title: t('desktopMenu.quit'),\n type: 'default'\n })\n\n if (!confirmed) return\n }\n\n electronAPI.quit()\n }\n }\n ],\n\n menuCommands: [\n {\n path: ['Help'],\n commands: ['Comfy-Desktop.OpenUserGuide']\n },\n {\n path: ['Help'],\n commands: ['Comfy-Desktop.OpenDevTools']\n },\n {\n path: ['Help', 'Open Folder'],\n commands: [\n 'Comfy-Desktop.Folders.OpenLogsFolder',\n 'Comfy-Desktop.Folders.OpenModelsFolder',\n 'Comfy-Desktop.Folders.OpenOutputsFolder',\n 'Comfy-Desktop.Folders.OpenInputsFolder',\n 'Comfy-Desktop.Folders.OpenCustomNodesFolder',\n 'Comfy-Desktop.Folders.OpenModelConfig'\n ]\n },\n {\n path: ['Help'],\n commands: ['Comfy-Desktop.CheckForUpdates', 'Comfy-Desktop.Reinstall']\n }\n ],\n\n keybindings: [\n {\n commandId: 'Workspace.CloseWorkflow',\n combo: {\n key: 'w',\n ctrl: true\n }\n }\n ],\n\n aboutPageBadges: [\n {\n label: 'ComfyUI_desktop v' + desktopAppVersion,\n url: staticUrls.githubElectron,\n icon: 'pi pi-github'\n }\n ]\n })\n})()\n","import type { GroupNodeHandler } from '@/extensions/core/groupNode'\nimport { ExecutableNodeDTO } from '@/lib/litegraph/src/litegraph'\nimport type {\n ExecutableLGraphNode,\n ExecutionId,\n LGraphNode,\n NodeId,\n SubgraphNode\n} from '@/lib/litegraph/src/litegraph'\n\nexport class ExecutableGroupNodeChildDTO extends ExecutableNodeDTO {\n groupNodeHandler?: GroupNodeHandler\n\n constructor(\n /** The actual node that this DTO wraps. */\n node: LGraphNode | SubgraphNode,\n /** A list of subgraph instance node IDs from the root graph to the containing instance. @see {@link id} */\n subgraphNodePath: readonly NodeId[],\n /** A flattened map of all DTOs in this node network. Subgraph instances have been expanded into their inner nodes. */\n nodesByExecutionId: Map<ExecutionId, ExecutableLGraphNode>,\n /** The actual subgraph instance that contains this node, otherwise undefined. */\n subgraphNode?: SubgraphNode | undefined,\n groupNodeHandler?: GroupNodeHandler\n ) {\n super(node, subgraphNodePath, nodesByExecutionId, subgraphNode)\n this.groupNodeHandler = groupNodeHandler\n }\n\n override resolveInput(slot: number) {\n // Check if this group node is inside a subgraph (unsupported)\n if (this.id.split(':').length > 2) {\n throw new Error(\n 'Group nodes inside subgraphs are not supported. Please convert the group node to a subgraph instead.'\n )\n }\n\n const inputNode = this.node.getInputNode(slot)\n if (!inputNode) return\n\n const link = this.node.getInputLink(slot)\n if (!link) throw new Error('Failed to get input link')\n\n const inputNodeId = String(inputNode.id)\n\n // Try to find the node using the full ID first (for nodes outside the group)\n let inputNodeDto = this.nodesByExecutionId?.get(inputNodeId)\n\n // If not found, try with just the last part of the ID (for nodes inside the group)\n if (!inputNodeDto) {\n const id = inputNodeId.split(':').at(-1)\n if (id !== undefined) {\n inputNodeDto = this.nodesByExecutionId?.get(id)\n }\n }\n\n if (!inputNodeDto) {\n throw new Error(\n `Failed to get input node ${inputNodeId} for group node child ${this.id} with slot ${slot}`\n )\n }\n\n return {\n node: inputNodeDto,\n origin_id: inputNodeId,\n origin_slot: link.origin_slot\n }\n }\n}\n","import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants'\nimport {\n type LGraphNode,\n type LGraphNodeConstructor,\n LiteGraph\n} from '@/lib/litegraph/src/litegraph'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\n\nimport { type ComfyApp, app } from '../../scripts/app'\nimport { $el } from '../../scripts/ui'\nimport { ComfyDialog } from '../../scripts/ui/dialog'\nimport { DraggableList } from '../../scripts/ui/draggableList'\nimport { GroupNodeConfig, GroupNodeHandler } from './groupNode'\nimport './groupNodeManage.css'\n\nconst ORDER: symbol = Symbol()\n\n// @ts-expect-error fixme ts strict error\nfunction merge(target, source) {\n if (typeof target === 'object' && typeof source === 'object') {\n for (const key in source) {\n const sv = source[key]\n if (typeof sv === 'object') {\n let tv = target[key]\n if (!tv) tv = target[key] = {}\n merge(tv, source[key])\n } else {\n target[key] = sv\n }\n }\n }\n\n return target\n}\n\nexport class ManageGroupDialog extends ComfyDialog<HTMLDialogElement> {\n // @ts-expect-error fixme ts strict error\n tabs: Record<\n 'Inputs' | 'Outputs' | 'Widgets',\n { tab: HTMLAnchorElement; page: HTMLElement }\n >\n selectedNodeIndex: number | null | undefined\n selectedTab: keyof ManageGroupDialog['tabs'] = 'Inputs'\n selectedGroup: string | undefined\n modifications: Record<\n string,\n Record<\n string,\n Record<\n string,\n { name?: string | undefined; visible?: boolean | undefined }\n >\n >\n > = {}\n // @ts-expect-error fixme ts strict error\n nodeItems: any[]\n app: ComfyApp\n // @ts-expect-error fixme ts strict error\n groupNodeType: LGraphNodeConstructor<LGraphNode>\n groupNodeDef: any\n groupData: any\n\n // @ts-expect-error fixme ts strict error\n innerNodesList: HTMLUListElement\n // @ts-expect-error fixme ts strict error\n widgetsPage: HTMLElement\n // @ts-expect-error fixme ts strict error\n inputsPage: HTMLElement\n // @ts-expect-error fixme ts strict error\n outputsPage: HTMLElement\n draggable: any\n\n get selectedNodeInnerIndex() {\n // @ts-expect-error fixme ts strict error\n return +this.nodeItems[this.selectedNodeIndex].dataset.nodeindex\n }\n\n // @ts-expect-error fixme ts strict error\n constructor(app) {\n super()\n this.app = app\n this.element = $el('dialog.comfy-group-manage', {\n parent: document.body\n }) as HTMLDialogElement\n }\n\n // @ts-expect-error fixme ts strict error\n changeTab(tab) {\n this.tabs[this.selectedTab].tab.classList.remove('active')\n this.tabs[this.selectedTab].page.classList.remove('active')\n // @ts-expect-error fixme ts strict error\n this.tabs[tab].tab.classList.add('active')\n // @ts-expect-error fixme ts strict error\n this.tabs[tab].page.classList.add('active')\n this.selectedTab = tab\n }\n\n // @ts-expect-error fixme ts strict error\n changeNode(index, force?) {\n if (!force && this.selectedNodeIndex === index) return\n\n if (this.selectedNodeIndex != null) {\n this.nodeItems[this.selectedNodeIndex].classList.remove('selected')\n }\n this.nodeItems[index].classList.add('selected')\n this.selectedNodeIndex = index\n\n if (!this.buildInputsPage() && this.selectedTab === 'Inputs') {\n this.changeTab('Widgets')\n }\n if (!this.buildWidgetsPage() && this.selectedTab === 'Widgets') {\n this.changeTab('Outputs')\n }\n if (!this.buildOutputsPage() && this.selectedTab === 'Outputs') {\n this.changeTab('Inputs')\n }\n\n this.changeTab(this.selectedTab)\n }\n\n getGroupData() {\n this.groupNodeType = LiteGraph.registered_node_types[\n `${PREFIX}${SEPARATOR}` + this.selectedGroup\n ] as unknown as LGraphNodeConstructor<LGraphNode>\n this.groupNodeDef = this.groupNodeType.nodeData\n this.groupData = GroupNodeHandler.getGroupData(this.groupNodeType)\n }\n\n // @ts-expect-error fixme ts strict error\n changeGroup(group, reset = true) {\n this.selectedGroup = group\n this.getGroupData()\n\n const nodes = this.groupData.nodeData.nodes\n // @ts-expect-error fixme ts strict error\n this.nodeItems = nodes.map((n, i) =>\n $el(\n 'li.draggable-item',\n {\n dataset: {\n nodeindex: n.index + ''\n },\n onclick: () => {\n this.changeNode(i)\n }\n },\n [\n $el('span.drag-handle'),\n $el(\n 'div',\n {\n textContent: n.title ?? n.type\n },\n n.title\n ? $el('span', {\n textContent: n.type\n })\n : []\n )\n ]\n )\n )\n\n this.innerNodesList.replaceChildren(...this.nodeItems)\n\n if (reset) {\n this.selectedNodeIndex = null\n this.changeNode(0)\n } else {\n const items = this.draggable.getAllItems()\n // @ts-expect-error fixme ts strict error\n let index = items.findIndex((item) => item.classList.contains('selected'))\n if (index === -1) index = this.selectedNodeIndex\n this.changeNode(index, true)\n }\n\n const ordered = [...nodes]\n this.draggable?.dispose()\n this.draggable = new DraggableList(this.innerNodesList, 'li')\n this.draggable.addEventListener(\n 'dragend',\n // @ts-expect-error fixme ts strict error\n ({ detail: { oldPosition, newPosition } }) => {\n if (oldPosition === newPosition) return\n ordered.splice(newPosition, 0, ordered.splice(oldPosition, 1)[0])\n for (let i = 0; i < ordered.length; i++) {\n this.storeModification({\n nodeIndex: ordered[i].index,\n section: ORDER,\n prop: 'order',\n value: i\n })\n }\n }\n )\n }\n\n storeModification(props: {\n nodeIndex?: number\n section: symbol\n prop: string\n value: any\n }) {\n const { nodeIndex, section, prop, value } = props\n // @ts-expect-error fixme ts strict error\n const groupMod = (this.modifications[this.selectedGroup] ??= {})\n const nodesMod = (groupMod.nodes ??= {})\n const nodeMod = (nodesMod[nodeIndex ?? this.selectedNodeInnerIndex] ??= {})\n const typeMod = (nodeMod[section] ??= {})\n if (typeof value === 'object') {\n const objMod = (typeMod[prop] ??= {})\n Object.assign(objMod, value)\n } else {\n typeMod[prop] = value\n }\n }\n\n // @ts-expect-error fixme ts strict error\n getEditElement(section, prop, value, placeholder, checked, checkable = true) {\n if (value === placeholder) value = ''\n\n const mods =\n // @ts-expect-error fixme ts strict error\n this.modifications[this.selectedGroup]?.nodes?.[\n this.selectedNodeInnerIndex\n ]?.[section]?.[prop]\n if (mods) {\n if (mods.name != null) {\n value = mods.name\n }\n if (mods.visible != null) {\n checked = mods.visible\n }\n }\n\n return $el('div', [\n $el('input', {\n value,\n placeholder,\n type: 'text',\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n this.storeModification({\n section,\n prop,\n value: { name: e.target.value }\n })\n }\n }),\n $el('label', { textContent: 'Visible' }, [\n $el('input', {\n type: 'checkbox',\n checked,\n disabled: !checkable,\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n this.storeModification({\n section,\n prop,\n value: { visible: !!e.target.checked }\n })\n }\n })\n ])\n ])\n }\n\n buildWidgetsPage() {\n const widgets =\n this.groupData.oldToNewWidgetMap[this.selectedNodeInnerIndex]\n const items = Object.keys(widgets ?? {})\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[this.selectedGroup]\n const config = type.config?.[this.selectedNodeInnerIndex]?.input\n this.widgetsPage.replaceChildren(\n ...items.map((oldName) => {\n return this.getEditElement(\n 'input',\n oldName,\n widgets[oldName],\n oldName,\n config?.[oldName]?.visible !== false\n )\n })\n )\n return !!items.length\n }\n\n buildInputsPage() {\n const inputs = this.groupData.nodeInputs[this.selectedNodeInnerIndex]\n const items = Object.keys(inputs ?? {})\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[this.selectedGroup]\n const config = type.config?.[this.selectedNodeInnerIndex]?.input\n this.inputsPage.replaceChildren(\n // @ts-expect-error fixme ts strict error\n ...items\n .map((oldName) => {\n let value = inputs[oldName]\n if (!value) {\n return\n }\n\n return this.getEditElement(\n 'input',\n oldName,\n value,\n oldName,\n config?.[oldName]?.visible !== false\n )\n })\n .filter(Boolean)\n )\n return !!items.length\n }\n\n buildOutputsPage() {\n const nodes = this.groupData.nodeData.nodes\n const innerNodeDef = this.groupData.getNodeDef(\n nodes[this.selectedNodeInnerIndex]\n )\n const outputs = innerNodeDef?.output ?? []\n const groupOutputs =\n this.groupData.oldToNewOutputMap[this.selectedNodeInnerIndex]\n\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[this.selectedGroup]\n const config = type.config?.[this.selectedNodeInnerIndex]?.output\n const node = this.groupData.nodeData.nodes[this.selectedNodeInnerIndex]\n const checkable = node.type !== 'PrimitiveNode'\n this.outputsPage.replaceChildren(\n ...outputs\n // @ts-expect-error fixme ts strict error\n .map((type, slot) => {\n const groupOutputIndex = groupOutputs?.[slot]\n const oldName = innerNodeDef.output_name?.[slot] ?? type\n let value = config?.[slot]?.name\n const visible = config?.[slot]?.visible || groupOutputIndex != null\n if (!value || value === oldName) {\n value = ''\n }\n return this.getEditElement(\n 'output',\n slot,\n value,\n oldName,\n visible,\n checkable\n )\n })\n .filter(Boolean)\n )\n return !!outputs.length\n }\n\n // @ts-expect-error fixme ts strict error\n show(type?) {\n const groupNodes = Object.keys(app.rootGraph.extra?.groupNodes ?? {}).sort(\n (a, b) => a.localeCompare(b)\n )\n\n this.innerNodesList = $el(\n 'ul.comfy-group-manage-list-items'\n ) as HTMLUListElement\n this.widgetsPage = $el('section.comfy-group-manage-node-page')\n this.inputsPage = $el('section.comfy-group-manage-node-page')\n this.outputsPage = $el('section.comfy-group-manage-node-page')\n const pages = $el('div', [\n this.widgetsPage,\n this.inputsPage,\n this.outputsPage\n ])\n\n this.tabs = [\n ['Inputs', this.inputsPage],\n ['Widgets', this.widgetsPage],\n ['Outputs', this.outputsPage]\n // @ts-expect-error fixme ts strict error\n ].reduce((p, [name, page]: [string, HTMLElement]) => {\n // @ts-expect-error fixme ts strict error\n p[name] = {\n tab: $el('a', {\n onclick: () => {\n this.changeTab(name)\n },\n textContent: name\n }),\n page\n }\n return p\n }, {}) as any\n\n const outer = $el('div.comfy-group-manage-outer', [\n $el('header', [\n $el('h2', 'Group Nodes'),\n $el(\n 'select',\n {\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n this.changeGroup(e.target.value)\n }\n },\n groupNodes.map((g) =>\n $el('option', {\n textContent: g,\n selected: `${PREFIX}${SEPARATOR}${g}` === type,\n value: g\n })\n )\n )\n ]),\n $el('main', [\n $el('section.comfy-group-manage-list', this.innerNodesList),\n $el('section.comfy-group-manage-node', [\n $el(\n 'header',\n Object.values(this.tabs).map((t) => t.tab)\n ),\n pages\n ])\n ]),\n $el('footer', [\n $el(\n 'button.comfy-btn',\n {\n onclick: () => {\n const node = app.rootGraph.nodes.find(\n (n) => n.type === `${PREFIX}${SEPARATOR}` + this.selectedGroup\n )\n if (node) {\n useToastStore().addAlert(\n 'This group node is in use in the current workflow, please first remove these.'\n )\n return\n }\n if (\n confirm(\n `Are you sure you want to remove the node: \"${this.selectedGroup}\"`\n )\n ) {\n // @ts-expect-error fixme ts strict error\n delete app.rootGraph.extra.groupNodes[this.selectedGroup]\n LiteGraph.unregisterNodeType(\n `${PREFIX}${SEPARATOR}` + this.selectedGroup\n )\n }\n this.show()\n }\n },\n 'Delete Group Node'\n ),\n $el(\n 'button.comfy-btn',\n {\n onclick: async () => {\n let nodesByType\n let recreateNodes = []\n const types = {}\n for (const g in this.modifications) {\n // @ts-expect-error fixme ts strict error\n const type = app.rootGraph.extra.groupNodes[g]\n let config = (type.config ??= {})\n\n let nodeMods = this.modifications[g]?.nodes\n if (nodeMods) {\n const keys = Object.keys(nodeMods)\n // @ts-expect-error fixme ts strict error\n if (nodeMods[keys[0]][ORDER]) {\n // If any node is reordered, they will all need sequencing\n const orderedNodes = []\n const orderedMods = {}\n const orderedConfig = {}\n\n for (const n of keys) {\n // @ts-expect-error fixme ts strict error\n const order = nodeMods[n][ORDER].order\n orderedNodes[order] = type.nodes[+n]\n // @ts-expect-error fixme ts strict error\n orderedMods[order] = nodeMods[n]\n orderedNodes[order].index = order\n }\n\n // Rewrite links\n for (const l of type.links) {\n if (l[0] != null) l[0] = type.nodes[l[0]].index\n if (l[2] != null) l[2] = type.nodes[l[2]].index\n }\n\n // Rewrite externals\n if (type.external) {\n for (const ext of type.external) {\n ext[0] = type.nodes[ext[0]]\n }\n }\n\n // Rewrite modifications\n for (const id of keys) {\n if (config[id]) {\n // @ts-expect-error fixme ts strict error\n orderedConfig[type.nodes[id].index] = config[id]\n }\n delete config[id]\n }\n\n type.nodes = orderedNodes\n nodeMods = orderedMods\n type.config = config = orderedConfig\n }\n\n merge(config, nodeMods)\n }\n\n // @ts-expect-error fixme ts strict error\n types[g] = type\n\n if (!nodesByType) {\n nodesByType = app.rootGraph.nodes.reduce((p, n) => {\n // @ts-expect-error fixme ts strict error\n p[n.type] ??= []\n // @ts-expect-error fixme ts strict error\n p[n.type].push(n)\n return p\n }, {})\n }\n\n // @ts-expect-error fixme ts strict error\n const nodes = nodesByType[`${PREFIX}${SEPARATOR}` + g]\n if (nodes) recreateNodes.push(...nodes)\n }\n\n await GroupNodeConfig.registerFromWorkflow(types, {})\n\n for (const node of recreateNodes) {\n node.recreate()\n }\n\n this.modifications = {}\n this.app.canvas.setDirty(true, true)\n this.changeGroup(this.selectedGroup, false)\n }\n },\n 'Save'\n ),\n $el(\n 'button.comfy-btn',\n { onclick: () => this.element.close() },\n 'Close'\n )\n ])\n ])\n\n this.element.replaceChildren(outer)\n this.changeGroup(\n type\n ? (groupNodes.find((g) => `${PREFIX}${SEPARATOR}${g}` === type) ??\n groupNodes[0])\n : groupNodes[0]\n )\n this.element.showModal()\n\n this.element.addEventListener('close', () => {\n this.draggable?.dispose()\n this.element.remove()\n })\n }\n}\n","import _ from 'es-toolkit/compat'\n\nimport type {\n ComboInputSpec,\n ComboInputSpecV2,\n FloatInputSpec,\n InputSpec,\n IntInputSpec,\n NumericInputOptions\n} from '@/schemas/nodeDefSchema'\nimport {\n getComboSpecComboOptions,\n getInputSpecType,\n isComboInputSpec,\n isFloatInputSpec,\n isIntInputSpec\n} from '@/schemas/nodeDefSchema'\n\nimport { lcm } from './mathUtil'\n\nconst IGNORE_KEYS = new Set<string>([\n 'default',\n 'forceInput',\n 'defaultInput',\n 'control_after_generate',\n 'multiline',\n 'tooltip',\n 'dynamicPrompts'\n])\n\nconst getRange = (options: NumericInputOptions) => {\n const min = options.min ?? -Infinity\n const max = options.max ?? Infinity\n return { min, max }\n}\n\nconst mergeNumericInputSpec = <T extends IntInputSpec | FloatInputSpec>(\n spec1: T,\n spec2: T\n): T | null => {\n const type = spec1[0]\n const options1 = spec1[1] ?? {}\n const options2 = spec2[1] ?? {}\n\n const range1 = getRange(options1)\n const range2 = getRange(options2)\n\n // If the ranges do not overlap, return null\n if (range1.min > range2.max || range1.max < range2.min) {\n return null\n }\n\n const step1 = options1.step ?? 1\n const step2 = options2.step ?? 1\n\n const mergedOptions = {\n // Take intersection of ranges\n min: Math.max(range1.min, range2.min),\n max: Math.min(range1.max, range2.max),\n step: lcm(step1, step2)\n }\n\n return mergeCommonInputSpec(\n [type, { ...options1, ...mergedOptions }] as T,\n [type, { ...options2, ...mergedOptions }] as T\n )\n}\n\nconst mergeComboInputSpec = <T extends ComboInputSpec | ComboInputSpecV2>(\n spec1: T,\n spec2: T\n): T | null => {\n const options1 = spec1[1] ?? {}\n const options2 = spec2[1] ?? {}\n\n const comboOptions1 = getComboSpecComboOptions(spec1)\n const comboOptions2 = getComboSpecComboOptions(spec2)\n\n const intersection = _.intersection(comboOptions1, comboOptions2)\n\n // If the intersection is empty, return null\n if (intersection.length === 0) {\n return null\n }\n\n return mergeCommonInputSpec(\n ['COMBO', { ...options1, options: intersection }] as T,\n ['COMBO', { ...options2, options: intersection }] as T\n )\n}\n\nconst mergeCommonInputSpec = <T extends InputSpec>(\n spec1: T,\n spec2: T\n): T | null => {\n const type = getInputSpecType(spec1)\n const options1 = spec1[1] ?? {}\n const options2 = spec2[1] ?? {}\n\n const compareKeys = _.union(_.keys(options1), _.keys(options2)).filter(\n (key) => !IGNORE_KEYS.has(key)\n )\n\n const mergeIsValid = compareKeys.every((key) => {\n const value1 = options1[key]\n const value2 = options2[key]\n return value1 === value2 || (_.isNil(value1) && _.isNil(value2))\n })\n\n return mergeIsValid ? ([type, { ...options1, ...options2 }] as T) : null\n}\n\n/**\n * Merges two input specs.\n *\n * @param spec1 - The first input spec.\n * @param spec2 - The second input spec.\n * @returns The merged input spec, or null if the specs are not mergeable.\n */\nexport const mergeInputSpec = (\n spec1: InputSpec,\n spec2: InputSpec\n): InputSpec | null => {\n const type1 = getInputSpecType(spec1)\n const type2 = getInputSpecType(spec2)\n\n if (type1 !== type2) {\n return null\n }\n\n if (isIntInputSpec(spec1) || isFloatInputSpec(spec1)) {\n return mergeNumericInputSpec(spec1, spec2 as typeof spec1)\n }\n\n if (isComboInputSpec(spec1)) {\n return mergeComboInputSpec(spec1, spec2 as typeof spec1)\n }\n\n return mergeCommonInputSpec(spec1, spec2)\n}\n","import type { PrimitiveNode } from '@/extensions/core/widgetInputs'\nimport type { LGraphNode } from '@/lib/litegraph/src/litegraph'\n\nexport const isPrimitiveNode = (\n node: LGraphNode\n): node is PrimitiveNode & LGraphNode => node.type === 'PrimitiveNode'\n","import {\n type CallbackParams,\n useChainCallback\n} from '@/composables/functional/useChainCallback'\nimport { LGraphNode, LiteGraph } from '@/lib/litegraph/src/litegraph'\nimport type {\n INodeInputSlot,\n INodeOutputSlot,\n ISlotType,\n LLink\n} from '@/lib/litegraph/src/litegraph'\nimport { NodeSlot } from '@/lib/litegraph/src/node/NodeSlot'\nimport type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'\nimport type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'\nimport type { InputSpec } from '@/schemas/nodeDefSchema'\nimport { app } from '@/scripts/app'\nimport {\n ComfyWidgets,\n addValueControlWidgets,\n isValidWidgetType\n} from '@/scripts/widgets'\nimport { CONFIG, GET_CONFIG } from '@/services/litegraphService'\nimport { mergeInputSpec } from '@/utils/nodeDefUtil'\nimport { applyTextReplacements } from '@/utils/searchAndReplace'\nimport { isPrimitiveNode } from '@/renderer/utils/nodeTypeGuards'\n\nconst replacePropertyName = 'Run widget replace on values'\nexport class PrimitiveNode extends LGraphNode {\n controlValues?: any[]\n lastType?: string\n static override category: string\n constructor(title: string) {\n super(title)\n this.addOutput('connect to widget input', '*')\n this.serialize_widgets = true\n this.isVirtualNode = true\n\n if (!this.properties || !(replacePropertyName in this.properties)) {\n this.addProperty(replacePropertyName, false, 'boolean')\n }\n }\n\n override applyToGraph(extraLinks: LLink[] = []) {\n if (!this.outputs[0].links?.length || !this.graph) return\n\n const links = [\n ...this.outputs[0].links.map((l) => this.graph!.links[l]),\n ...extraLinks\n ]\n let v = this.widgets?.[0].value\n if (v && this.properties[replacePropertyName]) {\n v = applyTextReplacements(this.graph, v as string)\n }\n\n // For each output link copy our value over the original widget value\n for (const linkInfo of links) {\n const node = this.graph?.getNodeById(linkInfo.target_id)\n const input = node?.inputs[linkInfo.target_slot]\n if (!input) {\n console.warn('Unable to resolve node or input for link', linkInfo)\n continue\n }\n\n const widgetName = input.widget?.name\n if (!widgetName) {\n console.warn('Invalid widget or widget name', input.widget)\n continue\n }\n\n const widget = node.widgets?.find((w) => w.name === widgetName)\n if (!widget) {\n console.warn(\n `Unable to find widget \"${widgetName}\" on node [${node.id}]`\n )\n continue\n }\n\n widget.value = v\n widget.callback?.(\n widget.value,\n app.canvas,\n node,\n app.canvas.graph_mouse,\n {} as CanvasPointerEvent\n )\n }\n }\n\n override refreshComboInNode() {\n const widget = this.widgets?.[0]\n if (widget?.type === 'combo') {\n // @ts-expect-error fixme ts strict error\n widget.options.values = this.outputs[0].widget[GET_CONFIG]()[0]\n\n // @ts-expect-error fixme ts strict error\n if (!widget.options.values.includes(widget.value as string)) {\n // @ts-expect-error fixme ts strict error\n widget.value = widget.options.values[0]\n ;(widget.callback as Function)(widget.value)\n }\n }\n }\n\n override onAfterGraphConfigured() {\n if (this.outputs[0].links?.length && !this.widgets?.length) {\n this.#onFirstConnection()\n\n // Populate widget values from config data\n if (this.widgets && this.widgets_values) {\n for (let i = 0; i < this.widgets_values.length; i++) {\n const w = this.widgets[i]\n if (w) {\n w.value = this.widgets_values[i] as any\n }\n }\n }\n\n // Merge values if required\n this.#mergeWidgetConfig()\n }\n }\n\n override onConnectionsChange(\n _type: ISlotType,\n _index: number,\n connected: boolean\n ) {\n if (app.configuringGraph) {\n // Dont run while the graph is still setting up\n return\n }\n\n const links = this.outputs[0].links\n if (connected) {\n if (links?.length && !this.widgets?.length) {\n this.#onFirstConnection()\n }\n } else {\n // We may have removed a link that caused the constraints to change\n this.#mergeWidgetConfig()\n\n if (!links?.length) {\n this.onLastDisconnect()\n }\n }\n }\n\n override onConnectOutput(\n slot: number,\n _type: string,\n input: INodeInputSlot,\n target_node: LGraphNode,\n target_slot: number\n ) {\n // Fires before the link is made allowing us to reject it if it isn't valid\n // No widget, we can't connect\n if (!input.widget && !(input.type in ComfyWidgets)) {\n return false\n }\n\n if (this.outputs[slot].links?.length) {\n const valid = this.#isValidConnection(input)\n if (valid) {\n // On connect of additional outputs, copy our value to their widget\n this.applyToGraph([{ target_id: target_node.id, target_slot } as LLink])\n }\n return valid\n }\n\n return true\n }\n\n #onFirstConnection(recreating?: boolean) {\n // First connection can fire before the graph is ready on initial load so random things can be missing\n if (!this.outputs[0].links || !this.graph) {\n this.onLastDisconnect()\n return\n }\n const linkId = this.outputs[0].links[0]\n const link = this.graph.links[linkId]\n if (!link) return\n\n const theirNode = this.graph.getNodeById(link.target_id)\n if (!theirNode || !theirNode.inputs) return\n\n const input = theirNode.inputs[link.target_slot]\n if (!input) return\n\n let widget\n if (!input.widget) {\n if (!(input.type in ComfyWidgets)) return\n widget = { name: input.name, [GET_CONFIG]: () => [input.type, {}] } //fake widget\n } else {\n widget = input.widget\n }\n\n // @ts-expect-error fixme ts strict error\n const config = widget[GET_CONFIG]?.()\n if (!config) return\n\n const { type } = getWidgetType(config)\n // Update our output to restrict to the widget type\n this.outputs[0].type = type\n this.outputs[0].name = type\n this.outputs[0].widget = widget\n\n this.#createWidget(\n widget[CONFIG] ?? config,\n theirNode,\n widget.name,\n // @ts-expect-error fixme ts strict error\n recreating\n )\n }\n\n #createWidget(\n inputData: InputSpec,\n node: LGraphNode,\n widgetName: string,\n recreating: boolean\n ) {\n let type = inputData[0]\n\n if (type instanceof Array) {\n type = 'COMBO'\n }\n\n // Store current size as addWidget resizes the node\n const [oldWidth, oldHeight] = this.size\n let widget: IBaseWidget\n if (isValidWidgetType(type)) {\n widget = (ComfyWidgets[type](this, 'value', inputData, app) || {}).widget\n } else {\n // @ts-expect-error InputSpec is not typed correctly\n widget = this.addWidget(type, 'value', null, () => {}, {})\n }\n\n if (node?.widgets && widget) {\n const theirWidget = node.widgets.find((w) => w.name === widgetName)\n if (theirWidget) {\n widget.value = theirWidget.value\n }\n }\n\n if (\n !inputData?.[1]?.control_after_generate &&\n (widget.type === 'number' || widget.type === 'combo')\n ) {\n let control_value = this.widgets_values?.[1]\n if (!control_value) {\n control_value = 'fixed'\n }\n addValueControlWidgets(\n this,\n widget,\n control_value as string,\n undefined,\n inputData\n )\n if (this.widgets?.[1]) widget.linkedWidgets = [this.widgets[1]]\n\n let filter = this.widgets_values?.[2]\n if (filter && this.widgets && this.widgets.length === 3) {\n this.widgets[2].value = filter\n }\n }\n\n // Restore any saved control values\n const controlValues = this.controlValues\n if (\n this.widgets &&\n this.lastType === this.widgets[0]?.type &&\n controlValues?.length === this.widgets.length - 1\n ) {\n for (let i = 0; i < controlValues.length; i++) {\n this.widgets[i + 1].value = controlValues[i]\n }\n }\n\n // When our value changes, update other widgets to reflect our changes\n // e.g. so LoadImage shows correct image\n widget.callback = useChainCallback(widget.callback, () => {\n this.applyToGraph()\n })\n\n // Use the biggest dimensions in case the widgets caused the node to grow\n this.setSize([\n Math.max(this.size[0], oldWidth),\n Math.max(this.size[1], oldHeight)\n ])\n\n if (!recreating) {\n // Grow our node more if required\n const sz = this.computeSize()\n if (this.size[0] < sz[0]) {\n this.size[0] = sz[0]\n }\n if (this.size[1] < sz[1]) {\n this.size[1] = sz[1]\n }\n\n requestAnimationFrame(() => {\n this.onResize?.(this.size)\n })\n }\n }\n\n recreateWidget() {\n const values = this.widgets?.map((w) => w.value)\n this.#removeWidgets()\n this.#onFirstConnection(true)\n if (values?.length && this.widgets) {\n for (let i = 0; i < this.widgets.length; i++)\n this.widgets[i].value = values[i]\n }\n return this.widgets?.[0]\n }\n\n #mergeWidgetConfig() {\n // Merge widget configs if the node has multiple outputs\n const output = this.outputs[0]\n const links = output.links ?? []\n\n const hasConfig = !!output.widget?.[CONFIG]\n if (hasConfig) {\n delete output.widget?.[CONFIG]\n }\n\n if (links?.length < 2 && hasConfig) {\n // Copy the widget options from the source\n if (links.length) {\n this.recreateWidget()\n }\n\n return\n }\n const config1 = (output.widget?.[GET_CONFIG] as () => InputSpec)?.()\n if (!config1) return\n const isNumber = config1[0] === 'INT' || config1[0] === 'FLOAT'\n if (!isNumber || !this.graph) return\n\n for (const linkId of links) {\n const link = this.graph.links[linkId]\n if (!link) continue // Can be null when removing a node\n\n const theirNode = this.graph.getNodeById(link.target_id)\n if (!theirNode) continue\n const theirInput = theirNode.inputs[link.target_slot]\n\n // Call is valid connection so it can merge the configs when validating\n this.#isValidConnection(theirInput, hasConfig)\n }\n }\n\n #isValidConnection(input: INodeInputSlot, forceUpdate?: boolean) {\n // Only allow connections where the configs match\n const output = this.outputs?.[0]\n const config2 = (input.widget?.[GET_CONFIG] as () => InputSpec)?.()\n if (!config2) return false\n\n return !!mergeIfValid.call(\n this,\n output,\n config2,\n forceUpdate,\n this.recreateWidget\n )\n }\n\n #removeWidgets() {\n if (this.widgets) {\n // Allow widgets to cleanup\n for (const w of this.widgets) {\n if (w.onRemove) {\n w.onRemove()\n }\n }\n\n // Temporarily store the current values in case the node is being recreated\n // e.g. by group node conversion\n this.controlValues = []\n this.lastType = this.widgets[0]?.type\n for (let i = 1; i < this.widgets.length; i++) {\n this.controlValues.push(this.widgets[i].value)\n }\n setTimeout(() => {\n delete this.lastType\n delete this.controlValues\n }, 15)\n this.widgets.length = 0\n }\n }\n\n onLastDisconnect() {\n // We can't remove + re-add the output here as if you drag a link over the same link\n // it removes, then re-adds, causing it to break\n this.outputs[0].type = '*'\n this.outputs[0].name = 'connect to widget input'\n delete this.outputs[0].widget\n\n this.#removeWidgets()\n }\n}\n\nexport function getWidgetConfig(\n slot: INodeInputSlot | INodeOutputSlot\n): InputSpec {\n return (slot.widget?.[CONFIG] ??\n (slot.widget?.[GET_CONFIG] as () => InputSpec)?.() ?? [\n '*',\n {}\n ]) as InputSpec\n}\n\nfunction getConfig(this: LGraphNode, widgetName: string) {\n const { nodeData } = this.constructor\n return (\n nodeData?.input?.required?.[widgetName] ??\n nodeData?.input?.optional?.[widgetName]\n )\n}\n\n/**\n * Convert a widget to an input slot.\n * @deprecated Widget to socket conversion is no longer necessary, as they co-exist now.\n * @param node The node to convert the widget to an input slot for.\n * @param widget The widget to convert to an input slot.\n * @returns The input slot that was converted from the widget or undefined if the widget is not found.\n * @knipIgnoreUnusedButUsedByCustomNodes\n */\nexport function convertToInput(\n node: LGraphNode,\n widget: IBaseWidget\n): INodeInputSlot | undefined {\n console.warn(\n 'Please remove call to convertToInput. Widget to socket conversion is no longer necessary, as they co-exist now.'\n )\n return node.inputs.find((slot) => slot.widget?.name === widget.name)\n}\n\nfunction getWidgetType(config: InputSpec) {\n // Special handling for COMBO so we restrict links based on the entries\n let type = config[0]\n if (type instanceof Array) {\n type = 'COMBO'\n }\n return { type }\n}\n\nexport function setWidgetConfig(slot: INodeInputSlot, config?: InputSpec) {\n if (!slot.widget) return\n if (config) {\n slot.widget[GET_CONFIG] = () => config\n } else {\n delete slot.widget\n }\n\n if (!(slot instanceof NodeSlot)) return\n const graph = slot.node.graph\n if (!graph) return\n const link = graph.links[slot.link ?? -1]\n if (!link) return\n const originNode = graph.getNodeById(link.origin_id)\n if (!originNode || !isPrimitiveNode(originNode)) return\n if (config) {\n originNode.recreateWidget()\n } else if (!app.configuringGraph) {\n originNode.disconnectOutput(0)\n originNode.onLastDisconnect()\n }\n}\n\nexport function mergeIfValid(\n output: INodeOutputSlot | INodeInputSlot,\n config2: InputSpec,\n forceUpdate?: boolean,\n recreateWidget?: () => void,\n config1?: InputSpec\n): { customConfig: InputSpec[1] } {\n if (!config1) {\n config1 = getWidgetConfig(output)\n }\n\n const customSpec = mergeInputSpec(config1, config2)\n\n if (customSpec || forceUpdate) {\n if (customSpec) {\n // @ts-expect-error fixme ts strict error\n output.widget[CONFIG] = customSpec\n }\n\n // @ts-expect-error fixme ts strict error\n const widget = recreateWidget?.call(this)\n // When deleting a node this can be null\n if (widget) {\n // @ts-expect-error fixme ts strict error\n const min = widget.options.min\n // @ts-expect-error fixme ts strict error\n const max = widget.options.max\n // @ts-expect-error fixme ts strict error\n if (min != null && widget.value < min) widget.value = min\n // @ts-expect-error fixme ts strict error\n if (max != null && widget.value > max) widget.value = max\n // @ts-expect-error fixme ts strict error\n widget.callback(widget.value)\n }\n }\n\n return { customConfig: customSpec?.[1] ?? {} }\n}\n\napp.registerExtension({\n name: 'Comfy.WidgetInputs',\n async beforeRegisterNodeDef(nodeType, _nodeData, app) {\n // @ts-expect-error adding extra property\n nodeType.prototype.convertWidgetToInput = function (this: LGraphNode) {\n console.warn(\n 'Please remove call to convertWidgetToInput. Widget to socket conversion is no longer necessary, as they co-exist now.'\n )\n return false\n }\n\n nodeType.prototype.onGraphConfigured = useChainCallback(\n nodeType.prototype.onGraphConfigured,\n function (this: LGraphNode) {\n if (!this.inputs) return\n this.widgets ??= []\n\n for (const input of this.inputs) {\n if (input.widget) {\n const name = input.widget.name\n if (!input.widget[GET_CONFIG]) {\n input.widget[GET_CONFIG] = () => getConfig.call(this, name)\n }\n\n const w = this.widgets?.find((w) => w.name === name)\n if (!w) {\n this.removeInput(this.inputs.findIndex((i) => i === input))\n }\n }\n }\n }\n )\n\n nodeType.prototype.onConfigure = useChainCallback(\n nodeType.prototype.onConfigure,\n function (this: LGraphNode) {\n if (!app.configuringGraph && this.inputs) {\n // On copy + paste of nodes, ensure that widget configs are set up\n for (const input of this.inputs) {\n if (input.widget && !input.widget[GET_CONFIG]) {\n const name = input.widget.name\n input.widget[GET_CONFIG] = () => getConfig.call(this, name)\n }\n }\n }\n }\n )\n\n // Double click a widget input to automatically attach a primitive\n const origOnInputDblClick = nodeType.prototype.onInputDblClick\n nodeType.prototype.onInputDblClick = function (\n this: LGraphNode,\n ...[slot, ...args]: CallbackParams<typeof origOnInputDblClick>\n ) {\n const r = origOnInputDblClick?.apply(this, [slot, ...args])\n\n const input = this.inputs[slot]\n if (!input.widget) {\n // Not a widget input or already handled input\n if (\n !(input.type in ComfyWidgets) &&\n !(\n (\n input.widget?.[GET_CONFIG] as (() => InputSpec) | undefined\n )?.()?.[0] instanceof Array\n )\n ) {\n return r //also Not a ComfyWidgets input or combo (do nothing)\n }\n }\n\n // Create a primitive node\n const node = LiteGraph.createNode('PrimitiveNode')\n const graph = app.canvas.graph\n if (!node || !graph) return r\n\n graph?.add(node)\n\n // Calculate a position that won't directly overlap another node\n const pos: [number, number] = [\n this.pos[0] - node.size[0] - 30,\n this.pos[1]\n ]\n while (graph.getNodeOnPos(pos[0], pos[1], graph.nodes))\n pos[1] += LiteGraph.NODE_TITLE_HEIGHT\n\n node.pos = pos\n node.connect(0, this, slot)\n node.title = input.name\n\n return r\n }\n },\n registerCustomNodes() {\n LiteGraph.registerNodeType(\n 'PrimitiveNode',\n Object.assign(PrimitiveNode, {\n title: 'Primitive'\n })\n )\n PrimitiveNode.category = 'utils'\n }\n})\n","import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants'\nimport { t } from '@/i18n'\nimport { type NodeId } from '@/lib/litegraph/src/LGraphNode'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport {\n type ExecutableLGraphNode,\n type ExecutionId,\n LGraphNode,\n LiteGraph,\n SubgraphNode\n} from '@/lib/litegraph/src/litegraph'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport {\n type ComfyLink,\n type ComfyNode,\n type ComfyWorkflowJSON\n} from '@/platform/workflow/validation/schemas/workflowSchema'\nimport type { ComfyNodeDef } from '@/schemas/nodeDefSchema'\nimport { useDialogService } from '@/services/dialogService'\nimport { useExecutionStore } from '@/stores/executionStore'\nimport { useNodeDefStore } from '@/stores/nodeDefStore'\nimport { useWidgetStore } from '@/stores/widgetStore'\nimport { type ComfyExtension } from '@/types/comfy'\nimport { ExecutableGroupNodeChildDTO } from '@/utils/executableGroupNodeChildDTO'\nimport { GROUP } from '@/utils/executableGroupNodeDto'\nimport { deserialiseAndCreate, serialise } from '@/utils/vintageClipboard'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\nimport { ManageGroupDialog } from './groupNodeManage'\nimport { mergeIfValid } from './widgetInputs'\n\ntype GroupNodeWorkflowData = {\n external: ComfyLink[]\n links: ComfyLink[]\n nodes: ComfyNode[]\n}\n\nconst Workflow = {\n InUse: {\n Free: 0,\n Registered: 1,\n InWorkflow: 2\n },\n // @ts-expect-error fixme ts strict error\n isInUseGroupNode(name) {\n const id = `${PREFIX}${SEPARATOR}${name}`\n // Check if lready registered/in use in this workflow\n // @ts-expect-error fixme ts strict error\n if (app.rootGraph.extra?.groupNodes?.[name]) {\n if (app.rootGraph.nodes.find((n) => n.type === id)) {\n return Workflow.InUse.InWorkflow\n } else {\n return Workflow.InUse.Registered\n }\n }\n return Workflow.InUse.Free\n },\n storeGroupNode(name: string, data: GroupNodeWorkflowData) {\n let extra = app.rootGraph.extra\n if (!extra) app.rootGraph.extra = extra = {}\n let groupNodes = extra.groupNodes\n if (!groupNodes) extra.groupNodes = groupNodes = {}\n // @ts-expect-error fixme ts strict error\n groupNodes[name] = data\n }\n}\n\nclass GroupNodeBuilder {\n nodes: LGraphNode[]\n // @ts-expect-error fixme ts strict error\n nodeData: GroupNodeWorkflowData\n\n constructor(nodes: LGraphNode[]) {\n this.nodes = nodes\n }\n\n async build() {\n const name = await this.getName()\n if (!name) return\n\n // Sort the nodes so they are in execution order\n // this allows for widgets to be in the correct order when reconstructing\n this.sortNodes()\n\n this.nodeData = this.getNodeData()\n Workflow.storeGroupNode(name, this.nodeData)\n\n return { name, nodeData: this.nodeData }\n }\n\n async getName() {\n const name = await useDialogService().prompt({\n title: t('groupNode.create'),\n message: t('groupNode.enterName'),\n defaultValue: ''\n })\n if (!name) return\n const used = Workflow.isInUseGroupNode(name)\n switch (used) {\n case Workflow.InUse.InWorkflow:\n useToastStore().addAlert(\n 'An in use group node with this name already exists embedded in this workflow, please remove any instances or use a new name.'\n )\n return\n case Workflow.InUse.Registered:\n if (\n !confirm(\n 'A group node with this name already exists embedded in this workflow, are you sure you want to overwrite it?'\n )\n ) {\n return\n }\n break\n }\n return name\n }\n\n sortNodes() {\n // Gets the builders nodes in graph execution order\n const nodesInOrder = app.rootGraph.computeExecutionOrder(false)\n this.nodes = this.nodes\n .map((node) => ({ index: nodesInOrder.indexOf(node), node }))\n // @ts-expect-error id might be string\n .sort((a, b) => a.index - b.index || a.node.id - b.node.id)\n .map(({ node }) => node)\n }\n\n getNodeData() {\n // @ts-expect-error fixme ts strict error\n const storeLinkTypes = (config) => {\n // Store link types for dynamically typed nodes e.g. reroutes\n for (const link of config.links) {\n const origin = app.rootGraph.getNodeById(link[4])\n // @ts-expect-error fixme ts strict error\n const type = origin.outputs[link[1]].type\n link.push(type)\n }\n }\n\n // @ts-expect-error fixme ts strict error\n const storeExternalLinks = (config) => {\n // Store any external links to the group in the config so when rebuilding we add extra slots\n config.external = []\n for (let i = 0; i < this.nodes.length; i++) {\n const node = this.nodes[i]\n if (!node.outputs?.length) continue\n for (let slot = 0; slot < node.outputs.length; slot++) {\n let hasExternal = false\n const output = node.outputs[slot]\n let type = output.type\n if (!output.links?.length) continue\n for (const l of output.links) {\n const link = app.rootGraph.links[l]\n if (!link) continue\n if (type === '*') type = link.type\n\n if (!app.canvas.selected_nodes[link.target_id]) {\n hasExternal = true\n break\n }\n }\n if (hasExternal) {\n config.external.push([i, slot, type])\n }\n }\n }\n }\n\n // Use the built in copyToClipboard function to generate the node data we need\n try {\n // @ts-expect-error fixme ts strict error\n const serialised = serialise(this.nodes, app.canvas?.graph)\n const config = JSON.parse(serialised)\n\n storeLinkTypes(config)\n storeExternalLinks(config)\n\n return config\n } finally {\n }\n }\n}\n\nexport class GroupNodeConfig {\n name: string\n nodeData: any\n inputCount: number\n oldToNewOutputMap: {}\n newToOldOutputMap: {}\n oldToNewInputMap: {}\n oldToNewWidgetMap: {}\n newToOldWidgetMap: {}\n primitiveDefs: {}\n widgetToPrimitive: {}\n primitiveToWidget: {}\n nodeInputs: {}\n outputVisibility: any[]\n // @ts-expect-error fixme ts strict error\n nodeDef: ComfyNodeDef\n // @ts-expect-error fixme ts strict error\n inputs: any[]\n // @ts-expect-error fixme ts strict error\n linksFrom: {}\n // @ts-expect-error fixme ts strict error\n linksTo: {}\n // @ts-expect-error fixme ts strict error\n externalFrom: {}\n\n // @ts-expect-error fixme ts strict error\n constructor(name, nodeData) {\n this.name = name\n this.nodeData = nodeData\n this.getLinks()\n\n this.inputCount = 0\n this.oldToNewOutputMap = {}\n this.newToOldOutputMap = {}\n this.oldToNewInputMap = {}\n this.oldToNewWidgetMap = {}\n this.newToOldWidgetMap = {}\n this.primitiveDefs = {}\n this.widgetToPrimitive = {}\n this.primitiveToWidget = {}\n this.nodeInputs = {}\n this.outputVisibility = []\n }\n\n async registerType(source = PREFIX) {\n this.nodeDef = {\n output: [],\n output_name: [],\n output_is_list: [],\n // @ts-expect-error Unused, doesn't exist\n output_is_hidden: [],\n name: source + SEPARATOR + this.name,\n display_name: this.name,\n category: 'group nodes' + (SEPARATOR + source),\n input: { required: {} },\n description: `Group node combining ${this.nodeData.nodes\n // @ts-expect-error fixme ts strict error\n .map((n) => n.type)\n .join(', ')}`,\n python_module: 'custom_nodes.' + this.name,\n\n [GROUP]: this\n }\n\n this.inputs = []\n const seenInputs = {}\n const seenOutputs = {}\n for (let i = 0; i < this.nodeData.nodes.length; i++) {\n const node = this.nodeData.nodes[i]\n node.index = i\n this.processNode(node, seenInputs, seenOutputs)\n }\n\n for (const p of this.#convertedToProcess) {\n // @ts-expect-error fixme ts strict error\n p()\n }\n // @ts-expect-error fixme ts strict error\n this.#convertedToProcess = null\n await app.registerNodeDef(`${PREFIX}${SEPARATOR}` + this.name, this.nodeDef)\n useNodeDefStore().addNodeDef(this.nodeDef)\n }\n\n getLinks() {\n this.linksFrom = {}\n this.linksTo = {}\n this.externalFrom = {}\n\n // Extract links for easy lookup\n for (const l of this.nodeData.links) {\n const [sourceNodeId, sourceNodeSlot, targetNodeId, targetNodeSlot] = l\n\n // Skip links outside the copy config\n if (sourceNodeId == null) continue\n\n // @ts-expect-error fixme ts strict error\n if (!this.linksFrom[sourceNodeId]) {\n // @ts-expect-error fixme ts strict error\n this.linksFrom[sourceNodeId] = {}\n }\n // @ts-expect-error fixme ts strict error\n if (!this.linksFrom[sourceNodeId][sourceNodeSlot]) {\n // @ts-expect-error fixme ts strict error\n this.linksFrom[sourceNodeId][sourceNodeSlot] = []\n }\n // @ts-expect-error fixme ts strict error\n this.linksFrom[sourceNodeId][sourceNodeSlot].push(l)\n\n // @ts-expect-error fixme ts strict error\n if (!this.linksTo[targetNodeId]) {\n // @ts-expect-error fixme ts strict error\n this.linksTo[targetNodeId] = {}\n }\n // @ts-expect-error fixme ts strict error\n this.linksTo[targetNodeId][targetNodeSlot] = l\n }\n\n if (this.nodeData.external) {\n for (const ext of this.nodeData.external) {\n // @ts-expect-error fixme ts strict error\n if (!this.externalFrom[ext[0]]) {\n // @ts-expect-error fixme ts strict error\n this.externalFrom[ext[0]] = { [ext[1]]: ext[2] }\n } else {\n // @ts-expect-error fixme ts strict error\n this.externalFrom[ext[0]][ext[1]] = ext[2]\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n processNode(node, seenInputs, seenOutputs) {\n const def = this.getNodeDef(node)\n if (!def) return\n\n const inputs = { ...def.input?.required, ...def.input?.optional }\n\n this.inputs.push(this.processNodeInputs(node, seenInputs, inputs))\n if (def.output?.length) this.processNodeOutputs(node, seenOutputs, def)\n }\n\n // @ts-expect-error fixme ts strict error\n getNodeDef(node) {\n // @ts-expect-error fixme ts strict error\n const def = globalDefs[node.type]\n if (def) return def\n\n // @ts-expect-error fixme ts strict error\n const linksFrom = this.linksFrom[node.index]\n if (node.type === 'PrimitiveNode') {\n // Skip as its not linked\n if (!linksFrom) return\n\n let type = linksFrom['0'][0][5]\n if (type === 'COMBO') {\n // Use the array items\n const source = node.outputs[0].widget.name\n const fromTypeName = this.nodeData.nodes[linksFrom['0'][0][2]].type\n // @ts-expect-error fixme ts strict error\n const fromType = globalDefs[fromTypeName]\n const input =\n fromType.input.required[source] ?? fromType.input.optional[source]\n type = input[0]\n }\n\n // @ts-expect-error fixme ts strict error\n const def = (this.primitiveDefs[node.index] = {\n input: {\n required: {\n value: [type, {}]\n }\n },\n output: [type],\n output_name: [],\n output_is_list: []\n })\n return def\n } else if (node.type === 'Reroute') {\n // @ts-expect-error fixme ts strict error\n const linksTo = this.linksTo[node.index]\n // @ts-expect-error fixme ts strict error\n if (linksTo && linksFrom && !this.externalFrom[node.index]?.[0]) {\n // Being used internally\n return null\n }\n\n let config = {}\n let rerouteType = '*'\n if (linksFrom) {\n for (const [, , id, slot] of linksFrom['0']) {\n const node = this.nodeData.nodes[id]\n const input = node.inputs[slot]\n if (rerouteType === '*') {\n rerouteType = input.type\n }\n if (input.widget) {\n // @ts-expect-error fixme ts strict error\n const targetDef = globalDefs[node.type]\n const targetWidget =\n targetDef.input.required[input.widget.name] ??\n targetDef.input.optional[input.widget.name]\n\n const widget = [targetWidget[0], config]\n const res = mergeIfValid(\n {\n // @ts-expect-error fixme ts strict error\n widget\n },\n targetWidget,\n false,\n null,\n widget\n )\n config = res?.customConfig ?? config\n }\n }\n } else if (linksTo) {\n const [id, slot] = linksTo['0']\n rerouteType = this.nodeData.nodes[id].outputs[slot].type\n } else {\n // Reroute used as a pipe\n for (const l of this.nodeData.links) {\n if (l[2] === node.index) {\n rerouteType = l[5]\n break\n }\n }\n if (rerouteType === '*') {\n // Check for an external link\n // @ts-expect-error fixme ts strict error\n const t = this.externalFrom[node.index]?.[0]\n if (t) {\n rerouteType = t\n }\n }\n }\n\n // @ts-expect-error\n config.forceInput = true\n return {\n input: {\n required: {\n [rerouteType]: [rerouteType, config]\n }\n },\n output: [rerouteType],\n output_name: [],\n output_is_list: []\n }\n }\n\n console.warn(\n 'Skipping virtual node ' +\n node.type +\n ' when building group node ' +\n this.name\n )\n }\n\n // @ts-expect-error fixme ts strict error\n getInputConfig(node, inputName, seenInputs, config, extra?) {\n const customConfig = this.nodeData.config?.[node.index]?.input?.[inputName]\n let name =\n customConfig?.name ??\n // @ts-expect-error fixme ts strict error\n node.inputs?.find((inp) => inp.name === inputName)?.label ??\n inputName\n let key = name\n let prefix = ''\n // Special handling for primitive to include the title if it is set rather than just \"value\"\n if ((node.type === 'PrimitiveNode' && node.title) || name in seenInputs) {\n prefix = `${node.title ?? node.type} `\n key = name = `${prefix}${inputName}`\n if (name in seenInputs) {\n name = `${prefix}${seenInputs[name]} ${inputName}`\n }\n }\n seenInputs[key] = (seenInputs[key] ?? 1) + 1\n\n if (inputName === 'seed' || inputName === 'noise_seed') {\n if (!extra) extra = {}\n extra.control_after_generate = `${prefix}control_after_generate`\n }\n if (config[0] === 'IMAGEUPLOAD') {\n if (!extra) extra = {}\n extra.widget =\n // @ts-expect-error fixme ts strict error\n this.oldToNewWidgetMap[node.index]?.[config[1]?.widget ?? 'image'] ??\n 'image'\n }\n\n if (extra) {\n config = [config[0], { ...config[1], ...extra }]\n }\n\n return { name, config, customConfig }\n }\n\n // @ts-expect-error fixme ts strict error\n processWidgetInputs(inputs, node, inputNames, seenInputs) {\n const slots = []\n const converted = new Map()\n // @ts-expect-error fixme ts strict error\n const widgetMap = (this.oldToNewWidgetMap[node.index] = {})\n for (const inputName of inputNames) {\n if (useWidgetStore().inputIsWidget(inputs[inputName])) {\n const convertedIndex = node.inputs?.findIndex(\n // @ts-expect-error fixme ts strict error\n (inp) => inp.name === inputName && inp.widget?.name === inputName\n )\n if (convertedIndex > -1) {\n // This widget has been converted to a widget\n // We need to store this in the correct position so link ids line up\n converted.set(convertedIndex, inputName)\n // @ts-expect-error fixme ts strict error\n widgetMap[inputName] = null\n } else {\n // Normal widget\n const { name, config } = this.getInputConfig(\n node,\n inputName,\n seenInputs,\n inputs[inputName]\n )\n // @ts-expect-error fixme ts strict error\n this.nodeDef.input.required[name] = config\n // @ts-expect-error fixme ts strict error\n widgetMap[inputName] = name\n // @ts-expect-error fixme ts strict error\n this.newToOldWidgetMap[name] = { node, inputName }\n }\n } else {\n // Normal input\n slots.push(inputName)\n }\n }\n return { converted, slots }\n }\n\n // @ts-expect-error fixme ts strict error\n checkPrimitiveConnection(link, inputName, inputs) {\n const sourceNode = this.nodeData.nodes[link[0]]\n if (sourceNode.type === 'PrimitiveNode') {\n // Merge link configurations\n const [sourceNodeId, _, targetNodeId, __] = link\n // @ts-expect-error fixme ts strict error\n const primitiveDef = this.primitiveDefs[sourceNodeId]\n const targetWidget = inputs[inputName]\n const primitiveConfig = primitiveDef.input.required.value\n const output = { widget: primitiveConfig }\n const config = mergeIfValid(\n // @ts-expect-error invalid slot type\n output,\n targetWidget,\n false,\n null,\n primitiveConfig\n )\n primitiveConfig[1] =\n (config?.customConfig ?? inputs[inputName][1])\n ? { ...inputs[inputName][1] }\n : {}\n\n // @ts-expect-error fixme ts strict error\n let name = this.oldToNewWidgetMap[sourceNodeId]['value']\n name = name.substr(0, name.length - 6)\n primitiveConfig[1].control_after_generate = true\n primitiveConfig[1].control_prefix = name\n\n // @ts-expect-error fixme ts strict error\n let toPrimitive = this.widgetToPrimitive[targetNodeId]\n if (!toPrimitive) {\n // @ts-expect-error fixme ts strict error\n toPrimitive = this.widgetToPrimitive[targetNodeId] = {}\n }\n if (toPrimitive[inputName]) {\n toPrimitive[inputName].push(sourceNodeId)\n }\n toPrimitive[inputName] = sourceNodeId\n\n // @ts-expect-error fixme ts strict error\n let toWidget = this.primitiveToWidget[sourceNodeId]\n if (!toWidget) {\n // @ts-expect-error fixme ts strict error\n toWidget = this.primitiveToWidget[sourceNodeId] = []\n }\n toWidget.push({ nodeId: targetNodeId, inputName })\n }\n }\n\n // @ts-expect-error fixme ts strict error\n processInputSlots(inputs, node, slots, linksTo, inputMap, seenInputs) {\n // @ts-expect-error fixme ts strict error\n this.nodeInputs[node.index] = {}\n for (let i = 0; i < slots.length; i++) {\n const inputName = slots[i]\n if (linksTo[i]) {\n this.checkPrimitiveConnection(linksTo[i], inputName, inputs)\n // This input is linked so we can skip it\n continue\n }\n\n const { name, config, customConfig } = this.getInputConfig(\n node,\n inputName,\n seenInputs,\n inputs[inputName]\n )\n\n // @ts-expect-error fixme ts strict error\n this.nodeInputs[node.index][inputName] = name\n if (customConfig?.visible === false) continue\n\n // @ts-expect-error fixme ts strict error\n this.nodeDef.input.required[name] = config\n inputMap[i] = this.inputCount++\n }\n }\n\n processConvertedWidgets(\n // @ts-expect-error fixme ts strict error\n inputs,\n // @ts-expect-error fixme ts strict error\n node,\n // @ts-expect-error fixme ts strict error\n slots,\n // @ts-expect-error fixme ts strict error\n converted,\n // @ts-expect-error fixme ts strict error\n linksTo,\n // @ts-expect-error fixme ts strict error\n inputMap,\n // @ts-expect-error fixme ts strict error\n seenInputs\n ) {\n // Add converted widgets sorted into their index order (ordered as they were converted) so link ids match up\n const convertedSlots = [...converted.keys()]\n .sort()\n .map((k) => converted.get(k))\n for (let i = 0; i < convertedSlots.length; i++) {\n const inputName = convertedSlots[i]\n if (linksTo[slots.length + i]) {\n this.checkPrimitiveConnection(\n linksTo[slots.length + i],\n inputName,\n inputs\n )\n // This input is linked so we can skip it\n continue\n }\n\n const { name, config } = this.getInputConfig(\n node,\n inputName,\n seenInputs,\n inputs[inputName],\n {\n defaultInput: true\n }\n )\n\n // @ts-expect-error fixme ts strict error\n this.nodeDef.input.required[name] = config\n // @ts-expect-error fixme ts strict error\n this.newToOldWidgetMap[name] = { node, inputName }\n\n // @ts-expect-error fixme ts strict error\n if (!this.oldToNewWidgetMap[node.index]) {\n // @ts-expect-error fixme ts strict error\n this.oldToNewWidgetMap[node.index] = {}\n }\n // @ts-expect-error fixme ts strict error\n this.oldToNewWidgetMap[node.index][inputName] = name\n\n inputMap[slots.length + i] = this.inputCount++\n }\n }\n\n #convertedToProcess = []\n // @ts-expect-error fixme ts strict error\n processNodeInputs(node, seenInputs, inputs) {\n // @ts-expect-error fixme ts strict error\n const inputMapping = []\n\n const inputNames = Object.keys(inputs)\n if (!inputNames.length) return\n\n const { converted, slots } = this.processWidgetInputs(\n inputs,\n node,\n inputNames,\n seenInputs\n )\n // @ts-expect-error fixme ts strict error\n const linksTo = this.linksTo[node.index] ?? {}\n // @ts-expect-error fixme ts strict error\n const inputMap = (this.oldToNewInputMap[node.index] = {})\n this.processInputSlots(inputs, node, slots, linksTo, inputMap, seenInputs)\n\n // Converted inputs have to be processed after all other nodes as they'll be at the end of the list\n // @ts-expect-error fixme ts strict error\n this.#convertedToProcess.push(() =>\n this.processConvertedWidgets(\n inputs,\n node,\n slots,\n converted,\n linksTo,\n inputMap,\n seenInputs\n )\n )\n\n // @ts-expect-error fixme ts strict error\n return inputMapping\n }\n\n // @ts-expect-error fixme ts strict error\n processNodeOutputs(node, seenOutputs, def) {\n // @ts-expect-error fixme ts strict error\n const oldToNew = (this.oldToNewOutputMap[node.index] = {})\n\n // Add outputs\n for (let outputId = 0; outputId < def.output.length; outputId++) {\n // @ts-expect-error fixme ts strict error\n const linksFrom = this.linksFrom[node.index]\n // If this output is linked internally we flag it to hide\n const hasLink =\n // @ts-expect-error fixme ts strict error\n linksFrom?.[outputId] && !this.externalFrom[node.index]?.[outputId]\n const customConfig =\n this.nodeData.config?.[node.index]?.output?.[outputId]\n const visible = customConfig?.visible ?? !hasLink\n this.outputVisibility.push(visible)\n if (!visible) {\n continue\n }\n\n // @ts-expect-error fixme ts strict error\n oldToNew[outputId] = this.nodeDef.output.length\n // @ts-expect-error fixme ts strict error\n this.newToOldOutputMap[this.nodeDef.output.length] = {\n node,\n slot: outputId\n }\n // @ts-expect-error fixme ts strict error\n this.nodeDef.output.push(def.output[outputId])\n // @ts-expect-error fixme ts strict error\n this.nodeDef.output_is_list.push(def.output_is_list[outputId])\n\n let label = customConfig?.name\n if (!label) {\n label = def.output_name?.[outputId] ?? def.output[outputId]\n // @ts-expect-error fixme ts strict error\n const output = node.outputs.find((o) => o.name === label)\n if (output?.label) {\n label = output.label\n }\n }\n\n let name = label\n if (name in seenOutputs) {\n const prefix = `${node.title ?? node.type} `\n name = `${prefix}${label}`\n if (name in seenOutputs) {\n name = `${prefix}${node.index} ${label}`\n }\n }\n seenOutputs[name] = 1\n\n // @ts-expect-error fixme ts strict error\n this.nodeDef.output_name.push(name)\n }\n }\n\n // @ts-expect-error fixme ts strict error\n static async registerFromWorkflow(groupNodes, missingNodeTypes) {\n for (const g in groupNodes) {\n const groupData = groupNodes[g]\n\n let hasMissing = false\n for (const n of groupData.nodes) {\n // Find missing node types\n if (!(n.type in LiteGraph.registered_node_types)) {\n missingNodeTypes.push({\n type: n.type,\n hint: ` (In group node '${PREFIX}${SEPARATOR}${g}')`\n })\n\n missingNodeTypes.push({\n type: `${PREFIX}${SEPARATOR}` + g,\n action: {\n text: 'Remove from workflow',\n // @ts-expect-error fixme ts strict error\n callback: (e) => {\n delete groupNodes[g]\n e.target.textContent = 'Removed'\n e.target.style.pointerEvents = 'none'\n e.target.style.opacity = 0.7\n }\n }\n })\n\n hasMissing = true\n }\n }\n\n if (hasMissing) continue\n\n const config = new GroupNodeConfig(g, groupData)\n await config.registerType()\n }\n }\n}\n\nexport class GroupNodeHandler {\n node: LGraphNode\n groupData: any\n innerNodes: any\n\n constructor(node: LGraphNode) {\n this.node = node\n this.groupData = node.constructor?.nodeData?.[GROUP]\n\n this.node.setInnerNodes = (innerNodes) => {\n this.innerNodes = innerNodes\n\n for (\n let innerNodeIndex = 0;\n innerNodeIndex < this.innerNodes.length;\n innerNodeIndex++\n ) {\n const innerNode = this.innerNodes[innerNodeIndex]\n innerNode.graph ??= this.node.graph\n\n for (const w of innerNode.widgets ?? []) {\n if (w.type === 'converted-widget') {\n w.serializeValue = w.origSerializeValue\n }\n }\n\n innerNode.index = innerNodeIndex\n // @ts-expect-error fixme ts strict error\n innerNode.getInputNode = (slot) => {\n // Check if this input is internal or external\n const externalSlot =\n this.groupData.oldToNewInputMap[innerNode.index]?.[slot]\n if (externalSlot != null) {\n return this.node.getInputNode(externalSlot)\n }\n\n // Internal link\n const innerLink = this.groupData.linksTo[innerNode.index]?.[slot]\n if (!innerLink) return null\n\n const inputNode = innerNodes[innerLink[0]]\n // Primitives will already apply their values\n if (inputNode.type === 'PrimitiveNode') return null\n\n return inputNode\n }\n\n // @ts-expect-error fixme ts strict error\n innerNode.getInputLink = (slot) => {\n const externalSlot =\n this.groupData.oldToNewInputMap[innerNode.index]?.[slot]\n if (externalSlot != null) {\n // The inner node is connected via the group node inputs\n const linkId = this.node.inputs[externalSlot].link\n // @ts-expect-error fixme ts strict error\n let link = app.rootGraph.links[linkId]\n\n // Use the outer link, but update the target to the inner node\n link = {\n ...link,\n target_id: innerNode.id,\n target_slot: +slot\n }\n return link\n }\n\n let link = this.groupData.linksTo[innerNode.index]?.[slot]\n if (!link) return null\n // Use the inner link, but update the origin node to be inner node id\n link = {\n origin_id: innerNodes[link[0]].id,\n origin_slot: link[1],\n target_id: innerNode.id,\n target_slot: +slot\n }\n return link\n }\n }\n }\n\n this.node.updateLink = (link) => {\n // Replace the group node reference with the internal node\n // @ts-expect-error Can this be removed? Or replaced with: LLink.create(link.asSerialisable())\n link = { ...link }\n const output = this.groupData.newToOldOutputMap[link.origin_slot]\n let innerNode = this.innerNodes[output.node.index]\n let l\n while (innerNode?.type === 'Reroute') {\n l = innerNode.getInputLink(0)\n innerNode = innerNode.getInputNode(0)\n }\n\n if (!innerNode) {\n return null\n }\n\n if (l && GroupNodeHandler.isGroupNode(innerNode)) {\n return innerNode.updateLink(l)\n }\n\n link.origin_id = innerNode.id\n link.origin_slot = l?.origin_slot ?? output.slot\n return link\n }\n\n /** @internal Used to flatten the subgraph before execution. Recursive; call with no args. */\n this.node.getInnerNodes = (\n computedNodeDtos: Map<ExecutionId, ExecutableLGraphNode>,\n /** The path of subgraph node IDs. */\n subgraphNodePath: readonly NodeId[] = [],\n /** The list of nodes to add to. */\n nodes: ExecutableLGraphNode[] = [],\n /** The set of visited nodes. */\n visited = new Set<LGraphNode>()\n ): ExecutableLGraphNode[] => {\n if (visited.has(this.node))\n throw new Error('RecursionError: while flattening subgraph')\n visited.add(this.node)\n\n if (!this.innerNodes) {\n // @ts-expect-error fixme ts strict error\n this.node.setInnerNodes(\n // @ts-expect-error fixme ts strict error\n this.groupData.nodeData.nodes.map((n, i) => {\n const innerNode = LiteGraph.createNode(n.type)\n // @ts-expect-error fixme ts strict error\n innerNode.configure(n)\n // @ts-expect-error fixme ts strict error\n innerNode.id = `${this.node.id}:${i}`\n // @ts-expect-error fixme ts strict error\n innerNode.graph = this.node.graph\n return innerNode\n })\n )\n }\n\n this.updateInnerWidgets()\n\n const subgraphInstanceIdPath = [...subgraphNodePath, this.node.id]\n\n // Assertion: Deprecated, does not matter.\n const subgraphNode = (this.node.graph?.getNodeById(\n subgraphNodePath.at(-1)\n ) ?? undefined) as SubgraphNode | undefined\n\n for (const node of this.innerNodes) {\n node.graph ??= this.node.graph\n\n // Create minimal DTOs rather than cloning the node\n const currentId = String(node.id)\n node.id = currentId.split(':').at(-1)\n const aVeryRealNode = new ExecutableGroupNodeChildDTO(\n node,\n subgraphInstanceIdPath,\n computedNodeDtos,\n subgraphNode\n )\n node.id = currentId\n aVeryRealNode.groupNodeHandler = this\n\n nodes.push(aVeryRealNode)\n }\n return nodes\n }\n\n // @ts-expect-error fixme ts strict error\n this.node.recreate = async () => {\n const id = this.node.id\n const sz = this.node.size\n // @ts-expect-error fixme ts strict error\n const nodes = this.node.convertToNodes()\n\n const groupNode = LiteGraph.createNode(this.node.type)\n // @ts-expect-error fixme ts strict error\n groupNode.id = id\n\n // Reuse the existing nodes for this instance\n // @ts-expect-error fixme ts strict error\n groupNode.setInnerNodes(nodes)\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].populateWidgets()\n // @ts-expect-error fixme ts strict error\n app.rootGraph.add(groupNode)\n // @ts-expect-error fixme ts strict error\n groupNode.setSize([\n // @ts-expect-error fixme ts strict error\n Math.max(groupNode.size[0], sz[0]),\n // @ts-expect-error fixme ts strict error\n Math.max(groupNode.size[1], sz[1])\n ])\n\n // Remove all converted nodes and relink them\n const builder = new GroupNodeBuilder(nodes)\n const nodeData = builder.getNodeData()\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].groupData.nodeData.links = nodeData.links\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].replaceNodes(nodes)\n return groupNode\n }\n\n // @ts-expect-error fixme ts strict error\n this.node.convertToNodes = () => {\n const addInnerNodes = () => {\n // Clone the node data so we dont mutate it for other nodes\n const c = { ...this.groupData.nodeData }\n c.nodes = [...c.nodes]\n // @ts-expect-error fixme ts strict error\n const innerNodes = this.node.getInnerNodes()\n let ids = []\n for (let i = 0; i < c.nodes.length; i++) {\n let id = innerNodes?.[i]?.id\n // Use existing IDs if they are set on the inner nodes\n // @ts-expect-error id can be string or number\n if (id == null || isNaN(id)) {\n // @ts-expect-error fixme ts strict error\n id = undefined\n } else {\n ids.push(id)\n }\n c.nodes[i] = { ...c.nodes[i], id }\n }\n deserialiseAndCreate(JSON.stringify(c), app.canvas)\n\n const [x, y] = this.node.pos\n let top\n let left\n // Configure nodes with current widget data\n const selectedIds = ids.length\n ? ids\n : Object.keys(app.canvas.selected_nodes)\n const newNodes = []\n for (let i = 0; i < selectedIds.length; i++) {\n const id = selectedIds[i]\n const newNode = app.rootGraph.getNodeById(id)\n const innerNode = innerNodes[i]\n newNodes.push(newNode)\n\n // @ts-expect-error fixme ts strict error\n if (left == null || newNode.pos[0] < left) {\n // @ts-expect-error fixme ts strict error\n left = newNode.pos[0]\n }\n // @ts-expect-error fixme ts strict error\n if (top == null || newNode.pos[1] < top) {\n // @ts-expect-error fixme ts strict error\n top = newNode.pos[1]\n }\n\n // @ts-expect-error fixme ts strict error\n if (!newNode.widgets) continue\n\n // @ts-expect-error fixme ts strict error\n const map = this.groupData.oldToNewWidgetMap[innerNode.index]\n if (map) {\n const widgets = Object.keys(map)\n\n for (const oldName of widgets) {\n const newName = map[oldName]\n if (!newName) continue\n\n // @ts-expect-error fixme ts strict error\n const widgetIndex = this.node.widgets.findIndex(\n (w) => w.name === newName\n )\n if (widgetIndex === -1) continue\n\n // Populate the main and any linked widgets\n if (innerNode.type === 'PrimitiveNode') {\n // @ts-expect-error fixme ts strict error\n for (let i = 0; i < newNode.widgets.length; i++) {\n // @ts-expect-error fixme ts strict error\n newNode.widgets[i].value =\n // @ts-expect-error fixme ts strict error\n this.node.widgets[widgetIndex + i].value\n }\n } else {\n // @ts-expect-error fixme ts strict error\n const outerWidget = this.node.widgets[widgetIndex]\n // @ts-expect-error fixme ts strict error\n const newWidget = newNode.widgets.find(\n (w) => w.name === oldName\n )\n if (!newWidget) continue\n\n newWidget.value = outerWidget.value\n // @ts-expect-error fixme ts strict error\n for (let w = 0; w < outerWidget.linkedWidgets?.length; w++) {\n // @ts-expect-error fixme ts strict error\n newWidget.linkedWidgets[w].value =\n // @ts-expect-error fixme ts strict error\n outerWidget.linkedWidgets[w].value\n }\n }\n }\n }\n }\n\n // Shift each node\n for (const newNode of newNodes) {\n // @ts-expect-error fixme ts strict error\n newNode.pos[0] -= left - x\n // @ts-expect-error fixme ts strict error\n newNode.pos[1] -= top - y\n }\n\n return { newNodes, selectedIds }\n }\n\n // @ts-expect-error fixme ts strict error\n const reconnectInputs = (selectedIds) => {\n for (const innerNodeIndex in this.groupData.oldToNewInputMap) {\n const id = selectedIds[innerNodeIndex]\n const newNode = app.rootGraph.getNodeById(id)\n const map = this.groupData.oldToNewInputMap[innerNodeIndex]\n for (const innerInputId in map) {\n const groupSlotId = map[innerInputId]\n if (groupSlotId == null) continue\n const slot = node.inputs[groupSlotId]\n if (slot.link == null) continue\n const link = app.rootGraph.links[slot.link]\n if (!link) continue\n // connect this node output to the input of another node\n const originNode = app.rootGraph.getNodeById(link.origin_id)\n // @ts-expect-error fixme ts strict error\n originNode.connect(link.origin_slot, newNode, +innerInputId)\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n const reconnectOutputs = (selectedIds) => {\n for (\n let groupOutputId = 0;\n groupOutputId < node.outputs?.length;\n groupOutputId++\n ) {\n const output = node.outputs[groupOutputId]\n if (!output.links) continue\n const links = [...output.links]\n for (const l of links) {\n const slot = this.groupData.newToOldOutputMap[groupOutputId]\n const link = app.rootGraph.links[l]\n const targetNode = app.rootGraph.getNodeById(link.target_id)\n const newNode = app.rootGraph.getNodeById(\n selectedIds[slot.node.index]\n )\n // @ts-expect-error fixme ts strict error\n newNode.connect(slot.slot, targetNode, link.target_slot)\n }\n }\n }\n\n app.canvas.emitBeforeChange()\n\n try {\n const { newNodes, selectedIds } = addInnerNodes()\n reconnectInputs(selectedIds)\n reconnectOutputs(selectedIds)\n app.rootGraph.remove(this.node)\n\n return newNodes\n } finally {\n app.canvas.emitAfterChange()\n }\n }\n\n const getExtraMenuOptions = this.node.getExtraMenuOptions\n // @ts-expect-error Should pass patched return value getExtraMenuOptions\n this.node.getExtraMenuOptions = function (_, options) {\n // @ts-expect-error fixme ts strict error\n getExtraMenuOptions?.apply(this, arguments)\n\n let optionIndex = options.findIndex((o) => o?.content === 'Outputs')\n if (optionIndex === -1) optionIndex = options.length\n else optionIndex++\n options.splice(\n optionIndex,\n 0,\n null,\n {\n content: 'Convert to nodes',\n // @ts-expect-error\n callback: () => {\n // @ts-expect-error fixme ts strict error\n return this.convertToNodes()\n }\n },\n {\n content: 'Manage Group Node',\n callback: () => manageGroupNodes(this.type)\n }\n )\n }\n\n // Draw custom collapse icon to identity this as a group\n const onDrawTitleBox = this.node.onDrawTitleBox\n this.node.onDrawTitleBox = function (ctx, height) {\n // @ts-expect-error fixme ts strict error\n onDrawTitleBox?.apply(this, arguments)\n\n const fill = ctx.fillStyle\n ctx.beginPath()\n ctx.rect(11, -height + 11, 2, 2)\n ctx.rect(14, -height + 11, 2, 2)\n ctx.rect(17, -height + 11, 2, 2)\n ctx.rect(11, -height + 14, 2, 2)\n ctx.rect(14, -height + 14, 2, 2)\n ctx.rect(17, -height + 14, 2, 2)\n ctx.rect(11, -height + 17, 2, 2)\n ctx.rect(14, -height + 17, 2, 2)\n ctx.rect(17, -height + 17, 2, 2)\n\n ctx.fillStyle = this.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR\n ctx.fill()\n ctx.fillStyle = fill\n }\n\n // Draw progress label\n const onDrawForeground = node.onDrawForeground\n const groupData = this.groupData.nodeData\n node.onDrawForeground = function (ctx) {\n // @ts-expect-error fixme ts strict error\n onDrawForeground?.apply?.(this, arguments)\n const progressState = useExecutionStore().nodeProgressStates[this.id]\n if (\n progressState &&\n progressState.state === 'running' &&\n this.runningInternalNodeId !== null\n ) {\n // @ts-expect-error fixme ts strict error\n const n = groupData.nodes[this.runningInternalNodeId]\n if (!n) return\n const message = `Running ${n.title || n.type} (${this.runningInternalNodeId}/${groupData.nodes.length})`\n ctx.save()\n ctx.font = '12px sans-serif'\n const sz = ctx.measureText(message)\n ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR\n ctx.beginPath()\n ctx.roundRect(\n 0,\n -LiteGraph.NODE_TITLE_HEIGHT - 20,\n sz.width + 12,\n 20,\n 5\n )\n ctx.fill()\n\n ctx.fillStyle = '#fff'\n ctx.fillText(message, 6, -LiteGraph.NODE_TITLE_HEIGHT - 6)\n ctx.restore()\n }\n }\n\n // Flag this node as needing to be reset\n const onExecutionStart = this.node.onExecutionStart\n this.node.onExecutionStart = function () {\n // @ts-expect-error fixme ts strict error\n this.resetExecution = true\n // @ts-expect-error fixme ts strict error\n return onExecutionStart?.apply(this, arguments)\n }\n\n const self = this\n const onNodeCreated = this.node.onNodeCreated\n this.node.onNodeCreated = function () {\n if (!this.widgets) {\n return\n }\n const config = self.groupData.nodeData.config\n if (config) {\n for (const n in config) {\n const inputs = config[n]?.input\n for (const w in inputs) {\n if (inputs[w].visible !== false) continue\n const widgetName = self.groupData.oldToNewWidgetMap[n][w]\n const widget = this.widgets.find((w) => w.name === widgetName)\n if (widget) {\n widget.type = 'hidden'\n widget.computeSize = () => [0, -4]\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n return onNodeCreated?.apply(this, arguments)\n }\n\n // @ts-expect-error fixme ts strict error\n function handleEvent(type, getId, getEvent) {\n // @ts-expect-error fixme ts strict error\n const handler = ({ detail }) => {\n const id = getId(detail)\n if (!id) return\n const node = app.rootGraph.getNodeById(id)\n if (node) return\n\n // @ts-expect-error fixme ts strict error\n const innerNodeIndex = this.innerNodes?.findIndex((n) => n.id == id)\n if (innerNodeIndex > -1) {\n // @ts-expect-error fixme ts strict error\n this.node.runningInternalNodeId = innerNodeIndex\n api.dispatchCustomEvent(\n type,\n // @ts-expect-error fixme ts strict error\n getEvent(detail, `${this.node.id}`, this.node)\n )\n }\n }\n api.addEventListener(type, handler)\n return handler\n }\n\n const executing = handleEvent.call(\n this,\n 'executing',\n // @ts-expect-error fixme ts strict error\n (d) => d,\n // @ts-expect-error fixme ts strict error\n (_, id) => id\n )\n\n const executed = handleEvent.call(\n this,\n 'executed',\n // @ts-expect-error fixme ts strict error\n (d) => d?.display_node || d?.node,\n // @ts-expect-error fixme ts strict error\n (d, id, node) => ({\n ...d,\n node: id,\n display_node: id,\n merge: !node.resetExecution\n })\n )\n\n const onRemoved = node.onRemoved\n this.node.onRemoved = function () {\n // @ts-expect-error fixme ts strict error\n onRemoved?.apply(this, arguments)\n // api.removeEventListener('progress_state', progress_state)\n api.removeEventListener('executing', executing)\n api.removeEventListener('executed', executed)\n }\n\n this.node.refreshComboInNode = (defs) => {\n // Update combo widget options\n for (const widgetName in this.groupData.newToOldWidgetMap) {\n // @ts-expect-error fixme ts strict error\n const widget = this.node.widgets.find((w) => w.name === widgetName)\n if (widget?.type === 'combo') {\n const old = this.groupData.newToOldWidgetMap[widgetName]\n const def = defs[old.node.type]\n const input =\n def?.input?.required?.[old.inputName] ??\n def?.input?.optional?.[old.inputName]\n if (!input) continue\n\n widget.options.values = input[0]\n\n if (\n old.inputName !== 'image' &&\n // @ts-expect-error Widget values\n !widget.options.values.includes(widget.value)\n ) {\n // @ts-expect-error fixme ts strict error\n widget.value = widget.options.values[0]\n // @ts-expect-error fixme ts strict error\n widget.callback(widget.value)\n }\n }\n }\n }\n }\n\n updateInnerWidgets() {\n for (const newWidgetName in this.groupData.newToOldWidgetMap) {\n // @ts-expect-error fixme ts strict error\n const newWidget = this.node.widgets.find((w) => w.name === newWidgetName)\n if (!newWidget) continue\n\n const newValue = newWidget.value\n const old = this.groupData.newToOldWidgetMap[newWidgetName]\n let innerNode = this.innerNodes[old.node.index]\n\n if (innerNode.type === 'PrimitiveNode') {\n innerNode.primitiveValue = newValue\n const primitiveLinked = this.groupData.primitiveToWidget[old.node.index]\n for (const linked of primitiveLinked ?? []) {\n const node = this.innerNodes[linked.nodeId]\n // @ts-expect-error fixme ts strict error\n const widget = node.widgets.find((w) => w.name === linked.inputName)\n\n if (widget) {\n widget.value = newValue\n }\n }\n continue\n } else if (innerNode.type === 'Reroute') {\n const rerouteLinks = this.groupData.linksFrom[old.node.index]\n if (rerouteLinks) {\n for (const [_, , targetNodeId, targetSlot] of rerouteLinks['0']) {\n const node = this.innerNodes[targetNodeId]\n const input = node.inputs[targetSlot]\n if (input.widget) {\n const widget = node.widgets?.find(\n // @ts-expect-error fixme ts strict error\n (w) => w.name === input.widget.name\n )\n if (widget) {\n widget.value = newValue\n }\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n const widget = innerNode.widgets?.find((w) => w.name === old.inputName)\n if (widget) {\n widget.value = newValue\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n populatePrimitive(_node, nodeId, oldName) {\n // Converted widget, populate primitive if linked\n const primitiveId = this.groupData.widgetToPrimitive[nodeId]?.[oldName]\n if (primitiveId == null) return\n const targetWidgetName =\n this.groupData.oldToNewWidgetMap[primitiveId]['value']\n // @ts-expect-error fixme ts strict error\n const targetWidgetIndex = this.node.widgets.findIndex(\n (w) => w.name === targetWidgetName\n )\n if (targetWidgetIndex > -1) {\n const primitiveNode = this.innerNodes[primitiveId]\n let len = primitiveNode.widgets.length\n if (\n len - 1 !==\n // @ts-expect-error fixme ts strict error\n this.node.widgets[targetWidgetIndex].linkedWidgets?.length\n ) {\n // Fallback handling for if some reason the primitive has a different number of widgets\n // we dont want to overwrite random widgets, better to leave blank\n len = 1\n }\n for (let i = 0; i < len; i++) {\n // @ts-expect-error fixme ts strict error\n this.node.widgets[targetWidgetIndex + i].value =\n primitiveNode.widgets[i].value\n }\n }\n return true\n }\n\n // @ts-expect-error fixme ts strict error\n populateReroute(node, nodeId, map) {\n if (node.type !== 'Reroute') return\n\n const link = this.groupData.linksFrom[nodeId]?.[0]?.[0]\n if (!link) return\n const [, , targetNodeId, targetNodeSlot] = link\n const targetNode = this.groupData.nodeData.nodes[targetNodeId]\n const inputs = targetNode.inputs\n const targetWidget = inputs?.[targetNodeSlot]?.widget\n if (!targetWidget) return\n\n const offset = inputs.length - (targetNode.widgets_values?.length ?? 0)\n const v = targetNode.widgets_values?.[targetNodeSlot - offset]\n if (v == null) return\n\n const widgetName = Object.values(map)[0]\n // @ts-expect-error fixme ts strict error\n const widget = this.node.widgets.find((w) => w.name === widgetName)\n if (widget) {\n widget.value = v\n }\n }\n\n populateWidgets() {\n if (!this.node.widgets) return\n\n for (\n let nodeId = 0;\n nodeId < this.groupData.nodeData.nodes.length;\n nodeId++\n ) {\n const node = this.groupData.nodeData.nodes[nodeId]\n const map = this.groupData.oldToNewWidgetMap[nodeId] ?? {}\n const widgets = Object.keys(map)\n\n if (!node.widgets_values?.length) {\n // special handling for populating values into reroutes\n // this allows primitives connect to them to pick up the correct value\n this.populateReroute(node, nodeId, map)\n continue\n }\n\n let linkedShift = 0\n for (let i = 0; i < widgets.length; i++) {\n const oldName = widgets[i]\n const newName = map[oldName]\n const widgetIndex = this.node.widgets.findIndex(\n (w) => w.name === newName\n )\n const mainWidget = this.node.widgets[widgetIndex]\n if (\n this.populatePrimitive(node, nodeId, oldName) ||\n widgetIndex === -1\n ) {\n // Find the inner widget and shift by the number of linked widgets as they will have been removed too\n const innerWidget = this.innerNodes[nodeId].widgets?.find(\n // @ts-expect-error fixme ts strict error\n (w) => w.name === oldName\n )\n linkedShift += innerWidget?.linkedWidgets?.length ?? 0\n }\n if (widgetIndex === -1) {\n continue\n }\n\n // Populate the main and any linked widget\n mainWidget.value = node.widgets_values[i + linkedShift]\n // @ts-expect-error fixme ts strict error\n for (let w = 0; w < mainWidget.linkedWidgets?.length; w++) {\n this.node.widgets[widgetIndex + w + 1].value =\n node.widgets_values[i + ++linkedShift]\n }\n }\n }\n }\n\n // @ts-expect-error fixme ts strict error\n replaceNodes(nodes) {\n let top\n let left\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]\n if (left == null || node.pos[0] < left) {\n left = node.pos[0]\n }\n if (top == null || node.pos[1] < top) {\n top = node.pos[1]\n }\n\n this.linkOutputs(node, i)\n app.rootGraph.remove(node)\n\n // Set internal ID to what is expected after workflow is reloaded\n node.id = `${this.node.id}:${i}`\n }\n\n this.linkInputs()\n this.node.pos = [left, top]\n }\n\n // @ts-expect-error fixme ts strict error\n linkOutputs(originalNode, nodeId) {\n if (!originalNode.outputs) return\n\n for (const output of originalNode.outputs) {\n if (!output.links) continue\n // Clone the links as they'll be changed if we reconnect\n const links = [...output.links]\n for (const l of links) {\n const link = app.rootGraph.links[l]\n if (!link) continue\n\n const targetNode = app.rootGraph.getNodeById(link.target_id)\n const newSlot =\n this.groupData.oldToNewOutputMap[nodeId]?.[link.origin_slot]\n if (newSlot != null) {\n // @ts-expect-error fixme ts strict error\n this.node.connect(newSlot, targetNode, link.target_slot)\n }\n }\n }\n }\n\n linkInputs() {\n for (const link of this.groupData.nodeData.links ?? []) {\n const [, originSlot, targetId, targetSlot, actualOriginId] = link\n const originNode = app.rootGraph.getNodeById(actualOriginId)\n if (!originNode) continue // this node is in the group\n originNode.connect(\n originSlot,\n // @ts-expect-error Valid - uses deprecated interface. Required check: if (graph.getNodeById(this.node.id) !== this.node) report()\n this.node.id,\n this.groupData.oldToNewInputMap[targetId][targetSlot]\n )\n }\n }\n\n // @ts-expect-error fixme ts strict error\n static getGroupData(node) {\n return (node.nodeData ?? node.constructor?.nodeData)?.[GROUP]\n }\n\n static isGroupNode(node: LGraphNode) {\n return !!node.constructor?.nodeData?.[GROUP]\n }\n\n static async fromNodes(nodes: LGraphNode[]) {\n // Process the nodes into the stored workflow group node data\n const builder = new GroupNodeBuilder(nodes)\n const res = await builder.build()\n if (!res) return\n\n const { name, nodeData } = res\n\n // Convert this data into a LG node definition and register it\n const config = new GroupNodeConfig(name, nodeData)\n await config.registerType()\n\n const groupNode = LiteGraph.createNode(`${PREFIX}${SEPARATOR}${name}`)\n // Reuse the existing nodes for this instance\n // @ts-expect-error fixme ts strict error\n groupNode.setInnerNodes(builder.nodes)\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].populateWidgets()\n // @ts-expect-error fixme ts strict error\n app.rootGraph.add(groupNode)\n\n // Remove all converted nodes and relink them\n // @ts-expect-error fixme ts strict error\n groupNode[GROUP].replaceNodes(builder.nodes)\n return groupNode\n }\n}\n\nconst replaceLegacySeparators = (nodes: ComfyNode[]): void => {\n for (const node of nodes) {\n if (typeof node.type === 'string' && node.type.startsWith('workflow/')) {\n node.type = node.type.replace(/^workflow\\//, `${PREFIX}${SEPARATOR}`)\n }\n }\n}\n\n/**\n * Convert selected nodes to a group node\n * @throws {Error} if no nodes are selected\n * @throws {Error} if a group node is already selected\n * @throws {Error} if a group node is selected\n *\n * The context menu item should not be available if any of the above conditions are met.\n * The error is automatically handled by the commandStore when the command is executed.\n */\nasync function convertSelectedNodesToGroupNode() {\n const nodes = Object.values(app.canvas.selected_nodes ?? {})\n if (nodes.length === 0) {\n throw new Error('No nodes selected')\n }\n if (nodes.length === 1) {\n throw new Error('Please select multiple nodes to convert to group node')\n }\n\n for (const node of nodes) {\n if (node instanceof SubgraphNode) {\n throw new Error('Selected nodes contain a subgraph node')\n }\n if (GroupNodeHandler.isGroupNode(node)) {\n throw new Error('Selected nodes contain a group node')\n }\n }\n return await GroupNodeHandler.fromNodes(nodes)\n}\n\nconst convertDisabled = (selected: LGraphNode[]) =>\n selected.length < 2 || !!selected.find((n) => GroupNodeHandler.isGroupNode(n))\n\nfunction ungroupSelectedGroupNodes() {\n const nodes = Object.values(app.canvas.selected_nodes ?? {})\n for (const node of nodes) {\n if (GroupNodeHandler.isGroupNode(node)) {\n node.convertToNodes?.()\n }\n }\n}\n\nfunction manageGroupNodes(type?: string) {\n new ManageGroupDialog(app).show(type)\n}\n\nconst id = 'Comfy.GroupNode'\n// @ts-expect-error fixme ts strict error\nlet globalDefs\nconst ext: ComfyExtension = {\n name: id,\n commands: [\n {\n id: 'Comfy.GroupNode.ConvertSelectedNodesToGroupNode',\n label: 'Convert selected nodes to group node',\n icon: 'pi pi-sitemap',\n versionAdded: '1.3.17',\n function: () => convertSelectedNodesToGroupNode()\n },\n {\n id: 'Comfy.GroupNode.UngroupSelectedGroupNodes',\n label: 'Ungroup selected group nodes',\n icon: 'pi pi-sitemap',\n versionAdded: '1.3.17',\n function: () => ungroupSelectedGroupNodes()\n },\n {\n id: 'Comfy.GroupNode.ManageGroupNodes',\n label: 'Manage group nodes',\n icon: 'pi pi-cog',\n versionAdded: '1.3.17',\n function: (...args: unknown[]) =>\n manageGroupNodes(args[0] as string | undefined)\n }\n ],\n keybindings: [\n {\n commandId: 'Comfy.GroupNode.ConvertSelectedNodesToGroupNode',\n combo: {\n alt: true,\n key: 'g'\n }\n },\n {\n commandId: 'Comfy.GroupNode.UngroupSelectedGroupNodes',\n combo: {\n alt: true,\n shift: true,\n key: 'G'\n }\n }\n ],\n\n getCanvasMenuItems(canvas): IContextMenuValue[] {\n const items: IContextMenuValue[] = []\n const selected = Object.values(canvas.selected_nodes ?? {})\n const convertEnabled = !convertDisabled(selected)\n\n items.push({\n content: `Convert to Group Node (Deprecated)`,\n disabled: !convertEnabled,\n // @ts-expect-error fixme ts strict error - async callback\n callback: () => convertSelectedNodesToGroupNode()\n })\n\n const groups = canvas.graph?.extra?.groupNodes\n const manageDisabled = !groups || !Object.keys(groups).length\n items.push({\n content: `Manage Group Nodes`,\n disabled: manageDisabled,\n callback: () => manageGroupNodes()\n })\n\n return items\n },\n\n getNodeMenuItems(node): IContextMenuValue[] {\n if (GroupNodeHandler.isGroupNode(node)) {\n return []\n }\n\n const selected = Object.values(app.canvas.selected_nodes ?? {})\n const convertEnabled = !convertDisabled(selected)\n\n return [\n {\n content: `Convert to Group Node (Deprecated)`,\n disabled: !convertEnabled,\n // @ts-expect-error fixme ts strict error - async callback\n callback: () => convertSelectedNodesToGroupNode()\n }\n ]\n },\n async beforeConfigureGraph(\n graphData: ComfyWorkflowJSON,\n missingNodeTypes: string[]\n ) {\n const nodes = graphData?.extra?.groupNodes\n if (nodes) {\n replaceLegacySeparators(graphData.nodes)\n await GroupNodeConfig.registerFromWorkflow(nodes, missingNodeTypes)\n }\n },\n addCustomNodeDefs(defs) {\n // Store this so we can mutate it later with group nodes\n globalDefs = defs\n },\n nodeCreated(node) {\n if (GroupNodeHandler.isGroupNode(node)) {\n // @ts-expect-error fixme ts strict error\n node[GROUP] = new GroupNodeHandler(node)\n\n // Ensure group nodes pasted from other workflows are stored\n // @ts-expect-error fixme ts strict error\n if (node.title && node[GROUP]?.groupData?.nodeData) {\n // @ts-expect-error fixme ts strict error\n Workflow.storeGroupNode(node.title, node[GROUP].groupData.nodeData)\n }\n }\n },\n // @ts-expect-error fixme ts strict error\n async refreshComboInNodes(defs) {\n // Re-register group nodes so new ones are created with the correct options\n // @ts-expect-error fixme ts strict error\n Object.assign(globalDefs, defs)\n const nodes = app.rootGraph.extra?.groupNodes\n if (nodes) {\n await GroupNodeConfig.registerFromWorkflow(nodes, {})\n }\n }\n}\n\napp.registerExtension(ext)\n","import type {\n IContextMenuValue,\n Positionable\n} from '@/lib/litegraph/src/interfaces'\nimport {\n LGraphCanvas,\n LGraphGroup,\n type LGraphNode\n} from '@/lib/litegraph/src/litegraph'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport type { ComfyExtension } from '@/types/comfy'\n\nimport { app } from '../../scripts/app'\n\nfunction setNodeMode(node: LGraphNode, mode: number) {\n node.mode = mode\n node.graph?.change()\n}\n\nfunction addNodesToGroup(group: LGraphGroup, items: Iterable<Positionable>) {\n const padding = useSettingStore().get('Comfy.GroupSelectedNodes.Padding')\n group.resizeTo([...group.children, ...items], padding)\n}\n\nconst ext: ComfyExtension = {\n name: 'Comfy.GroupOptions',\n\n getCanvasMenuItems(canvas: LGraphCanvas): IContextMenuValue[] {\n const items: IContextMenuValue[] = []\n\n // @ts-expect-error fixme ts strict error\n const group = canvas.graph.getGroupOnPos(\n canvas.graph_mouse[0],\n canvas.graph_mouse[1]\n )\n\n if (!group) {\n if (canvas.selectedItems.size > 0) {\n items.push({\n content: 'Add Group For Selected Nodes',\n callback: () => {\n const group = new LGraphGroup()\n addNodesToGroup(group, canvas.selectedItems)\n // @ts-expect-error fixme ts strict error\n canvas.graph.add(group)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n\n group.recomputeInsideNodes()\n }\n })\n }\n\n return items\n }\n\n // Group nodes aren't recomputed until the group is moved, this ensures the nodes are up-to-date\n group.recomputeInsideNodes()\n const nodesInGroup = group.nodes\n\n items.push({\n content: 'Add Selected Nodes To Group',\n disabled: !canvas.selectedItems?.size,\n callback: () => {\n addNodesToGroup(group, canvas.selectedItems)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n }\n })\n\n // No nodes in group, return default options\n if (nodesInGroup.length === 0) {\n return items\n } else {\n // Add a separator between the default options and the group options\n // @ts-expect-error fixme ts strict error\n items.push(null)\n }\n\n // Check if all nodes are the same mode\n let allNodesAreSameMode = true\n for (let i = 1; i < nodesInGroup.length; i++) {\n if (nodesInGroup[i].mode !== nodesInGroup[0].mode) {\n allNodesAreSameMode = false\n break\n }\n }\n\n items.push({\n content: 'Fit Group To Nodes',\n callback: () => {\n group.recomputeInsideNodes()\n const padding = useSettingStore().get(\n 'Comfy.GroupSelectedNodes.Padding'\n )\n group.resizeTo(group.children, padding)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n }\n })\n\n items.push({\n content: 'Select Nodes',\n callback: () => {\n canvas.selectNodes(nodesInGroup)\n // @ts-expect-error fixme ts strict error\n canvas.graph.change()\n canvas.canvas.focus()\n }\n })\n\n // Modes\n // 0: Always\n // 1: On Event\n // 2: Never\n // 3: On Trigger\n // 4: Bypass\n // If all nodes are the same mode, add a menu option to change the mode\n if (allNodesAreSameMode) {\n const mode = nodesInGroup[0].mode\n switch (mode) {\n case 0:\n // All nodes are always, option to disable, and bypass\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n break\n case 2:\n // All nodes are never, option to enable, and bypass\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n break\n case 4:\n // All nodes are bypass, option to enable, and disable\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n break\n default:\n // All nodes are On Trigger or On Event(Or other?), option to disable, set to always, or bypass\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n break\n }\n } else {\n // Nodes are not all the same mode, add a menu option to change the mode to always, never, or bypass\n items.push({\n content: 'Set Group Nodes to Always',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 0)\n }\n }\n })\n items.push({\n content: 'Set Group Nodes to Never',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 2)\n }\n }\n })\n items.push({\n content: 'Bypass Group Nodes',\n callback: () => {\n for (const node of nodesInGroup) {\n setNodeMode(node, 4)\n }\n }\n })\n }\n\n return items\n }\n}\n\napp.registerExtension(ext)\n","import type { NodeExecutionOutput } from '@/schemas/apiSchema'\nimport { api } from '@/scripts/api'\nimport { app } from '@/scripts/app'\nimport { useExtensionService } from '@/services/extensionService'\n\nuseExtensionService().registerExtension({\n name: 'Comfy.ImageCompare',\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'ImageCompare') return\n\n const [oldWidth, oldHeight] = node.size\n node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 350)])\n\n const onExecuted = node.onExecuted\n\n node.onExecuted = function (output: NodeExecutionOutput) {\n onExecuted?.call(this, output)\n\n const aImages = (output as Record<string, unknown>).a_images as\n | Record<string, string>[]\n | undefined\n const bImages = (output as Record<string, unknown>).b_images as\n | Record<string, string>[]\n | undefined\n const rand = app.getRandParam()\n\n const beforeUrl =\n aImages && aImages.length > 0\n ? api.apiURL(`/view?${new URLSearchParams(aImages[0])}${rand}`)\n : ''\n const afterUrl =\n bImages && bImages.length > 0\n ? api.apiURL(`/view?${new URLSearchParams(bImages[0])}${rand}`)\n : ''\n\n const widget = node.widgets?.find((w) => w.type === 'imagecompare')\n\n if (widget) {\n widget.value = {\n before: beforeUrl,\n after: afterUrl\n }\n widget.callback?.(widget.value)\n }\n }\n }\n})\n","import { t } from '@/i18n'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport Load3d from '@/extensions/core/load3d/Load3d'\nimport { LiteGraph } from '@/lib/litegraph/src/litegraph'\n\nconst EXPORT_FORMATS = [\n { label: 'GLB', value: 'glb' },\n { label: 'OBJ', value: 'obj' },\n { label: 'STL', value: 'stl' }\n] as const\n\n/**\n * Creates export menu items for a 3D node using the new extension API.\n * Returns an array of context menu items including a separator and export submenu.\n */\nexport function createExportMenuItems(\n load3d: Load3d\n): (IContextMenuValue | null)[] {\n return [\n null, // Separator\n {\n content: 'Save',\n has_submenu: true,\n callback: (_value, _options, event, prev_menu) => {\n const submenuOptions: IContextMenuValue[] = EXPORT_FORMATS.map(\n (format) => ({\n content: format.label,\n callback: () => {\n void (async () => {\n try {\n await load3d.exportModel(format.value)\n useToastStore().add({\n severity: 'success',\n summary: t('toastMessages.exportSuccess', {\n format: format.label\n })\n })\n } catch (error) {\n console.error('Export failed:', error)\n useToastStore().addAlert(\n t('toastMessages.failedToExportModel', {\n format: format.label\n })\n )\n }\n })()\n }\n })\n )\n\n new LiteGraph.ContextMenu(submenuOptions, {\n event,\n parentMenu: prev_menu\n })\n }\n }\n ]\n}\n","import Load3d from '@/extensions/core/load3d/Load3d'\nimport Load3dUtils from '@/extensions/core/load3d/Load3dUtils'\nimport type {\n CameraConfig,\n CameraState,\n LightConfig,\n ModelConfig,\n SceneConfig\n} from '@/extensions/core/load3d/interfaces'\nimport type { Dictionary } from '@/lib/litegraph/src/interfaces'\nimport type { NodeProperty } from '@/lib/litegraph/src/LGraphNode'\nimport type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport { api } from '@/scripts/api'\n\ntype Load3DConfigurationSettings = {\n loadFolder: string\n modelWidget: IBaseWidget\n cameraState?: CameraState\n width?: IBaseWidget\n height?: IBaseWidget\n bgImagePath?: string\n}\n\nclass Load3DConfiguration {\n constructor(\n private load3d: Load3d,\n private properties?: Dictionary<NodeProperty | undefined>\n ) {}\n\n configureForSaveMesh(loadFolder: 'input' | 'output', filePath: string) {\n this.setupModelHandlingForSaveMesh(filePath, loadFolder)\n this.setupDefaultProperties()\n }\n\n configure(setting: Load3DConfigurationSettings) {\n this.setupModelHandling(\n setting.modelWidget,\n setting.loadFolder,\n setting.cameraState\n )\n this.setupTargetSize(setting.width, setting.height)\n this.setupDefaultProperties(setting.bgImagePath)\n }\n\n private setupTargetSize(width?: IBaseWidget, height?: IBaseWidget) {\n if (width && height) {\n this.load3d.setTargetSize(width.value as number, height.value as number)\n\n width.callback = (value: number) => {\n this.load3d.setTargetSize(value, height.value as number)\n }\n\n height.callback = (value: number) => {\n this.load3d.setTargetSize(width.value as number, value)\n }\n }\n }\n\n private setupModelHandlingForSaveMesh(filePath: string, loadFolder: string) {\n const onModelWidgetUpdate = this.createModelUpdateHandler(loadFolder)\n\n if (filePath) {\n onModelWidgetUpdate(filePath)\n }\n }\n\n private setupModelHandling(\n modelWidget: IBaseWidget,\n loadFolder: string,\n cameraState?: CameraState\n ) {\n const onModelWidgetUpdate = this.createModelUpdateHandler(\n loadFolder,\n cameraState\n )\n if (modelWidget.value) {\n onModelWidgetUpdate(modelWidget.value)\n }\n\n const originalCallback = modelWidget.callback\n\n let currentValue = modelWidget.value\n Object.defineProperty(modelWidget, 'value', {\n get() {\n return currentValue\n },\n set(newValue) {\n currentValue = newValue\n if (modelWidget.callback && newValue !== undefined && newValue !== '') {\n modelWidget.callback(newValue)\n }\n },\n enumerable: true,\n configurable: true\n })\n\n modelWidget.callback = (value: string | number | boolean | object) => {\n onModelWidgetUpdate(value)\n\n if (originalCallback) {\n originalCallback(value)\n }\n }\n }\n\n private setupDefaultProperties(bgImagePath?: string) {\n const sceneConfig = this.loadSceneConfig()\n this.applySceneConfig(sceneConfig, bgImagePath)\n\n const cameraConfig = this.loadCameraConfig()\n this.applyCameraConfig(cameraConfig)\n\n const lightConfig = this.loadLightConfig()\n this.applyLightConfig(lightConfig)\n }\n\n private loadSceneConfig(): SceneConfig {\n if (this.properties && 'Scene Config' in this.properties) {\n return this.properties['Scene Config'] as SceneConfig\n }\n\n return {\n showGrid: useSettingStore().get('Comfy.Load3D.ShowGrid'),\n backgroundColor:\n '#' + useSettingStore().get('Comfy.Load3D.BackgroundColor'),\n backgroundImage: ''\n } as SceneConfig\n }\n\n private loadCameraConfig(): CameraConfig {\n if (this.properties && 'Camera Config' in this.properties) {\n return this.properties['Camera Config'] as CameraConfig\n }\n\n return {\n cameraType: useSettingStore().get('Comfy.Load3D.CameraType'),\n fov: 35\n } as CameraConfig\n }\n\n private loadLightConfig(): LightConfig {\n if (this.properties && 'Light Config' in this.properties) {\n return this.properties['Light Config'] as LightConfig\n }\n\n return {\n intensity: useSettingStore().get('Comfy.Load3D.LightIntensity')\n } as LightConfig\n }\n\n private loadModelConfig(): ModelConfig {\n if (this.properties && 'Model Config' in this.properties) {\n return this.properties['Model Config'] as ModelConfig\n }\n\n return {\n upDirection: 'original',\n materialMode: 'original'\n } as ModelConfig\n }\n\n private applySceneConfig(config: SceneConfig, bgImagePath?: string) {\n this.load3d.toggleGrid(config.showGrid)\n this.load3d.setBackgroundColor(config.backgroundColor)\n if (config.backgroundImage) {\n if (bgImagePath && bgImagePath != config.backgroundImage) {\n return\n }\n\n void this.load3d.setBackgroundImage(config.backgroundImage)\n\n if (config.backgroundRenderMode) {\n this.load3d.setBackgroundRenderMode(config.backgroundRenderMode)\n }\n }\n }\n\n private applyCameraConfig(config: CameraConfig) {\n this.load3d.toggleCamera(config.cameraType)\n this.load3d.setFOV(config.fov)\n\n if (config.state) {\n this.load3d.setCameraState(config.state)\n }\n }\n\n private applyLightConfig(config: LightConfig) {\n this.load3d.setLightIntensity(config.intensity)\n }\n\n private applyModelConfig(config: ModelConfig) {\n this.load3d.setUpDirection(config.upDirection)\n this.load3d.setMaterialMode(config.materialMode)\n }\n\n private createModelUpdateHandler(\n loadFolder: string,\n cameraState?: CameraState\n ) {\n let isFirstLoad = true\n return async (value: string | number | boolean | object) => {\n if (!value) return\n\n const filename = value as string\n\n this.setResourceFolder(filename)\n\n const modelUrl = api.apiURL(\n Load3dUtils.getResourceURL(\n ...Load3dUtils.splitFilePath(filename),\n loadFolder\n )\n )\n\n await this.load3d.loadModel(modelUrl, filename)\n\n const modelConfig = this.loadModelConfig()\n this.applyModelConfig(modelConfig)\n\n if (isFirstLoad && cameraState) {\n try {\n this.load3d.setCameraState(cameraState)\n } catch (error) {\n console.warn('Failed to restore camera state:', error)\n }\n isFirstLoad = false\n }\n }\n }\n\n private setResourceFolder(filename: string): void {\n const pathParts = filename.split('/').filter((part) => part.trim())\n\n if (pathParts.length <= 2) {\n return\n }\n\n const subfolderParts = pathParts.slice(1, -1)\n const subfolder = subfolderParts.join('/')\n\n if (subfolder && this.properties) {\n this.properties['Resource Folder'] = subfolder\n }\n }\n}\n\nexport default Load3DConfiguration\n","import { nextTick } from 'vue'\n\nimport Load3D from '@/components/load3d/Load3D.vue'\nimport Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'\nimport { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d'\nimport { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'\nimport Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'\nimport Load3dUtils from '@/extensions/core/load3d/Load3dUtils'\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport type { IStringWidget } from '@/lib/litegraph/src/types/widgets'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport { api } from '@/scripts/api'\nimport { ComfyApp, app } from '@/scripts/app'\nimport { ComponentWidgetImpl, addWidget } from '@/scripts/domWidget'\nimport { useExtensionService } from '@/services/extensionService'\nimport { useLoad3dService } from '@/services/load3dService'\nimport { useDialogStore } from '@/stores/dialogStore'\nimport { isLoad3dNode } from '@/utils/litegraphUtil'\n\nconst inputSpecLoad3D: CustomInputSpec = {\n name: 'image',\n type: 'Load3D',\n isPreview: false\n}\n\nconst inputSpecPreview3D: CustomInputSpec = {\n name: 'image',\n type: 'Preview3D',\n isPreview: true\n}\n\nasync function handleModelUpload(files: FileList, node: any) {\n if (!files?.length) return\n\n const modelWidget = node.widgets?.find(\n (w: any) => w.name === 'model_file'\n ) as IStringWidget\n\n try {\n const resourceFolder = (node.properties['Resource Folder'] as string) || ''\n\n const subfolder = resourceFolder.trim()\n ? `3d/${resourceFolder.trim()}`\n : '3d'\n\n const uploadPath = await Load3dUtils.uploadFile(files[0], subfolder)\n\n if (!uploadPath) {\n useToastStore().addAlert(t('toastMessages.fileUploadFailed'))\n return\n }\n\n const modelUrl = api.apiURL(\n Load3dUtils.getResourceURL(\n ...Load3dUtils.splitFilePath(uploadPath),\n 'input'\n )\n )\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n try {\n load3d.loadModel(modelUrl)\n } catch (error) {\n useToastStore().addAlert(t('toastMessages.failedToLoadModel'))\n }\n })\n\n if (uploadPath && modelWidget) {\n if (!modelWidget.options?.values?.includes(uploadPath)) {\n modelWidget.options?.values?.push(uploadPath)\n }\n\n modelWidget.value = uploadPath\n }\n } catch (error) {\n console.error('Model upload failed:', error)\n useToastStore().addAlert(t('toastMessages.fileUploadFailed'))\n }\n}\n\nasync function handleResourcesUpload(files: FileList, node: any) {\n if (!files?.length) return\n\n try {\n const resourceFolder = (node.properties['Resource Folder'] as string) || ''\n\n const subfolder = resourceFolder.trim()\n ? `3d/${resourceFolder.trim()}`\n : '3d'\n\n await Load3dUtils.uploadMultipleFiles(files, subfolder)\n } catch (error) {\n console.error('Extra resources upload failed:', error)\n useToastStore().addAlert(t('toastMessages.extraResourcesUploadFailed'))\n }\n}\n\nfunction createFileInput(\n accept: string,\n multiple: boolean = false\n): HTMLInputElement {\n const input = document.createElement('input')\n input.type = 'file'\n input.accept = accept\n input.multiple = multiple\n input.style.display = 'none'\n return input\n}\n\nuseExtensionService().registerExtension({\n name: 'Comfy.Load3D',\n settings: [\n {\n id: 'Comfy.Load3D.ShowGrid',\n category: ['3D', 'Scene', 'Initial Grid Visibility'],\n name: 'Initial Grid Visibility',\n tooltip:\n 'Controls whether the grid is visible by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.',\n type: 'boolean',\n defaultValue: true,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.BackgroundColor',\n category: ['3D', 'Scene', 'Initial Background Color'],\n name: 'Initial Background Color',\n tooltip:\n 'Controls the default background color of the 3D scene. This setting determines the background appearance when a new 3D widget is created, but can be adjusted individually for each widget after creation.',\n type: 'color',\n defaultValue: '282828',\n experimental: true\n },\n {\n id: 'Comfy.Load3D.CameraType',\n category: ['3D', 'Camera', 'Initial Camera Type'],\n name: 'Initial Camera Type',\n tooltip:\n 'Controls whether the camera is perspective or orthographic by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.',\n type: 'combo',\n options: ['perspective', 'orthographic'],\n defaultValue: 'perspective',\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightIntensity',\n category: ['3D', 'Light', 'Initial Light Intensity'],\n name: 'Initial Light Intensity',\n tooltip:\n 'Sets the default brightness level of lighting in the 3D scene. This value determines how intensely lights illuminate objects when a new 3D widget is created, but can be adjusted individually for each widget after creation.',\n type: 'number',\n defaultValue: 3,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightIntensityMaximum',\n category: ['3D', 'Light', 'Light Intensity Maximum'],\n name: 'Light Intensity Maximum',\n tooltip:\n 'Sets the maximum allowable light intensity value for 3D scenes. This defines the upper brightness limit that can be set when adjusting lighting in any 3D widget.',\n type: 'number',\n defaultValue: 10,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightIntensityMinimum',\n category: ['3D', 'Light', 'Light Intensity Minimum'],\n name: 'Light Intensity Minimum',\n tooltip:\n 'Sets the minimum allowable light intensity value for 3D scenes. This defines the lower brightness limit that can be set when adjusting lighting in any 3D widget.',\n type: 'number',\n defaultValue: 1,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.LightAdjustmentIncrement',\n category: ['3D', 'Light', 'Light Adjustment Increment'],\n name: 'Light Adjustment Increment',\n tooltip:\n 'Controls the increment size when adjusting light intensity in 3D scenes. A smaller step value allows for finer control over lighting adjustments, while a larger value results in more noticeable changes per adjustment.',\n type: 'slider',\n attrs: {\n min: 0.1,\n max: 1,\n step: 0.1\n },\n defaultValue: 0.5,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.3DViewerEnable',\n category: ['3D', '3DViewer', 'Enable'],\n name: 'Enable 3D Viewer (Beta)',\n tooltip:\n 'Enables the 3D Viewer (Beta) for selected nodes. This feature allows you to visualize and interact with 3D models directly within the full size 3d viewer.',\n type: 'boolean',\n defaultValue: false,\n experimental: true\n },\n {\n id: 'Comfy.Load3D.PLYEngine',\n category: ['3D', 'PLY', 'PLY Engine'],\n name: 'PLY Engine',\n tooltip:\n 'Select the engine for loading PLY files. \"threejs\" uses the native Three.js PLYLoader (best for mesh PLY files). \"fastply\" uses an optimized loader for ASCII point cloud PLY files. \"sparkjs\" uses Spark.js for 3D Gaussian Splatting PLY files.',\n type: 'combo',\n options: ['threejs', 'fastply', 'sparkjs'],\n defaultValue: 'threejs',\n experimental: true\n }\n ],\n commands: [\n {\n id: 'Comfy.3DViewer.Open3DViewer',\n icon: 'pi pi-pencil',\n label: 'Open 3D Viewer (Beta) for Selected Node',\n function: () => {\n const selectedNodes = app.canvas.selected_nodes\n if (!selectedNodes || Object.keys(selectedNodes).length !== 1) return\n\n const selectedNode = selectedNodes[Object.keys(selectedNodes)[0]]\n\n if (!isLoad3dNode(selectedNode)) return\n\n ComfyApp.copyToClipspace(selectedNode)\n // @ts-expect-error clipspace_return_node is an extension property added at runtime\n ComfyApp.clipspace_return_node = selectedNode\n\n const props = { node: selectedNode }\n\n useDialogStore().showDialog({\n key: 'global-load3d-viewer',\n title: t('load3d.viewer.title'),\n component: Load3DViewerContent,\n props: props,\n dialogComponentProps: {\n style: 'width: 80vw; height: 80vh;',\n maximizable: true,\n onClose: async () => {\n await useLoad3dService().handleViewerClose(props.node)\n }\n }\n })\n }\n }\n ],\n getCustomWidgets() {\n return {\n LOAD_3D(node) {\n const fileInput = createFileInput(\n '.gltf,.glb,.obj,.fbx,.stl,.ply,.spz,.splat,.ksplat',\n false\n )\n\n node.properties['Resource Folder'] = ''\n\n fileInput.onchange = async () => {\n await handleModelUpload(fileInput.files!, node)\n }\n\n node.addWidget('button', 'upload 3d model', 'upload3dmodel', () => {\n fileInput.click()\n })\n\n const resourcesInput = createFileInput('*', true)\n\n resourcesInput.onchange = async () => {\n await handleResourcesUpload(resourcesInput.files!, node)\n resourcesInput.value = ''\n }\n\n node.addWidget(\n 'button',\n 'upload extra resources',\n 'uploadExtraResources',\n () => {\n resourcesInput.click()\n }\n )\n\n node.addWidget('button', 'clear', 'clear', () => {\n useLoad3d(node).waitForLoad3d((load3d) => {\n load3d.clearModel()\n })\n\n const modelWidget = node.widgets?.find((w) => w.name === 'model_file')\n if (modelWidget) {\n modelWidget.value = ''\n }\n })\n\n const widget = new ComponentWidgetImpl({\n node: node,\n name: 'image',\n component: Load3D,\n inputSpec: inputSpecLoad3D,\n options: {}\n })\n\n widget.type = 'load3D'\n\n addWidget(node, widget)\n\n return { widget }\n }\n }\n },\n\n getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] {\n // Only show menu items for Load3D nodes\n if (node.constructor.comfyClass !== 'Load3D') return []\n\n const load3d = useLoad3dService().getLoad3d(node)\n if (!load3d) return []\n\n if (load3d.isSplatModel()) return []\n\n return createExportMenuItems(load3d)\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'Load3D') return\n\n const [oldWidth, oldHeight] = node.size\n\n node.setSize([Math.max(oldWidth, 300), Math.max(oldHeight, 600)])\n\n await nextTick()\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n const cameraConfig = node.properties['Camera Config'] as any\n const cameraState = cameraConfig?.state\n\n const config = new Load3DConfiguration(load3d, node.properties)\n\n const modelWidget = node.widgets?.find((w) => w.name === 'model_file')\n const width = node.widgets?.find((w) => w.name === 'width')\n const height = node.widgets?.find((w) => w.name === 'height')\n const sceneWidget = node.widgets?.find((w) => w.name === 'image')\n\n if (modelWidget && width && height && sceneWidget) {\n const settings = {\n loadFolder: 'input',\n modelWidget: modelWidget,\n cameraState: cameraState,\n width: width,\n height: height\n }\n config.configure(settings)\n\n sceneWidget.serializeValue = async () => {\n const currentLoad3d = nodeToLoad3dMap.get(node)\n if (!currentLoad3d) {\n console.error('No load3d instance found for node')\n return null\n }\n\n const cameraConfig = (node.properties['Camera Config'] as any) || {\n cameraType: currentLoad3d.getCurrentCameraType(),\n fov: currentLoad3d.cameraManager.perspectiveCamera.fov\n }\n cameraConfig.state = currentLoad3d.getCameraState()\n node.properties['Camera Config'] = cameraConfig\n\n currentLoad3d.stopRecording()\n\n const {\n scene: imageData,\n mask: maskData,\n normal: normalData\n } = await currentLoad3d.captureScene(\n width.value as number,\n height.value as number\n )\n\n const [data, dataMask, dataNormal] = await Promise.all([\n Load3dUtils.uploadTempImage(imageData, 'scene'),\n Load3dUtils.uploadTempImage(maskData, 'scene_mask'),\n Load3dUtils.uploadTempImage(normalData, 'scene_normal')\n ])\n\n currentLoad3d.handleResize()\n\n const returnVal = {\n image: `threed/${data.name} [temp]`,\n mask: `threed/${dataMask.name} [temp]`,\n normal: `threed/${dataNormal.name} [temp]`,\n camera_info:\n (node.properties['Camera Config'] as any)?.state || null,\n recording: ''\n }\n\n const recordingData = currentLoad3d.getRecordingData()\n\n if (recordingData) {\n const [recording] = await Promise.all([\n Load3dUtils.uploadTempImage(recordingData, 'recording', 'mp4')\n ])\n returnVal['recording'] = `threed/${recording.name} [temp]`\n }\n\n return returnVal\n }\n }\n })\n }\n})\n\nuseExtensionService().registerExtension({\n name: 'Comfy.Preview3D',\n\n async beforeRegisterNodeDef(_nodeType, nodeData) {\n if ('Preview3D' === nodeData.name) {\n // @ts-expect-error InputSpec is not typed correctly\n nodeData.input.required.image = ['PREVIEW_3D']\n }\n },\n\n getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] {\n // Only show menu items for Preview3D nodes\n if (node.constructor.comfyClass !== 'Preview3D') return []\n\n const load3d = useLoad3dService().getLoad3d(node)\n if (!load3d) return []\n\n if (load3d.isSplatModel()) return []\n\n return createExportMenuItems(load3d)\n },\n\n getCustomWidgets() {\n return {\n PREVIEW_3D(node) {\n const widget = new ComponentWidgetImpl({\n node,\n name: inputSpecPreview3D.name,\n component: Load3D,\n inputSpec: inputSpecPreview3D,\n options: {}\n })\n\n widget.type = 'load3D'\n\n addWidget(node, widget)\n\n return { widget }\n }\n }\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'Preview3D') return\n\n const [oldWidth, oldHeight] = node.size\n\n node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 550)])\n\n await nextTick()\n\n const onExecuted = node.onExecuted\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n const config = new Load3DConfiguration(load3d, node.properties)\n\n const modelWidget = node.widgets?.find((w) => w.name === 'model_file')\n\n if (modelWidget) {\n const lastTimeModelFile = node.properties['Last Time Model File']\n\n if (lastTimeModelFile) {\n modelWidget.value = lastTimeModelFile\n\n const cameraConfig = node.properties['Camera Config'] as any\n const cameraState = cameraConfig?.state\n\n const settings = {\n loadFolder: 'output',\n modelWidget: modelWidget,\n cameraState: cameraState\n }\n\n config.configure(settings)\n }\n\n node.onExecuted = function (message: any) {\n onExecuted?.apply(this, arguments as any)\n\n let filePath = message.result[0]\n\n if (!filePath) {\n const msg = t('toastMessages.unableToGetModelFilePath')\n console.error(msg)\n useToastStore().addAlert(msg)\n }\n\n let cameraState = message.result[1]\n let bgImagePath = message.result[2]\n\n modelWidget.value = filePath.replaceAll('\\\\', '/')\n\n node.properties['Last Time Model File'] = modelWidget.value\n\n const settings = {\n loadFolder: 'output',\n modelWidget: modelWidget,\n cameraState: cameraState,\n bgImagePath: bgImagePath\n }\n\n config.configure(settings)\n\n if (bgImagePath) {\n load3d.setBackgroundImage(bgImagePath)\n }\n }\n }\n })\n }\n})\n","import _ from 'es-toolkit/compat'\nimport type { LGraphNode } from '@/lib/litegraph/src/litegraph'\n\nimport { app, ComfyApp } from '@/scripts/app'\nimport { useMaskEditorStore } from '@/stores/maskEditorStore'\nimport { useDialogStore } from '@/stores/dialogStore'\nimport { useMaskEditor } from '@/composables/maskeditor/useMaskEditor'\n\nfunction openMaskEditor(node: LGraphNode): void {\n if (!node) {\n console.error('[MaskEditor] No node provided')\n return\n }\n\n if (!node.imgs?.length && node.previewMediaType !== 'image') {\n console.error('[MaskEditor] Node has no images')\n return\n }\n\n useMaskEditor().openMaskEditor(node)\n}\n\n// Open mask editor from clipspace (for plugin compatibility)\n// This is called when ComfyApp.open_maskeditor() is invoked without arguments\nfunction openMaskEditorFromClipspace(): void {\n const node = ComfyApp.clipspace_return_node as LGraphNode | null\n if (!node) {\n console.error('[MaskEditor] No clipspace_return_node found')\n return\n }\n\n openMaskEditor(node)\n}\n\n// Check if the dialog is already opened\nfunction isOpened(): boolean {\n return useDialogStore().isDialogOpen('global-mask-editor')\n}\n\nconst changeBrushSize = async (sizeChanger: (oldSize: number) => number) => {\n if (!isOpened()) return\n\n const store = useMaskEditorStore()\n const oldBrushSize = store.brushSettings.size\n const newBrushSize = sizeChanger(oldBrushSize)\n store.setBrushSize(newBrushSize)\n}\n\napp.registerExtension({\n name: 'Comfy.MaskEditor',\n settings: [\n {\n id: 'Comfy.MaskEditor.BrushAdjustmentSpeed',\n category: ['Mask Editor', 'BrushAdjustment', 'Sensitivity'],\n name: 'Brush adjustment speed multiplier',\n tooltip:\n 'Controls how quickly the brush size and hardness change when adjusting. Higher values mean faster changes.',\n type: 'slider',\n attrs: {\n min: 0.1,\n max: 2.0,\n step: 0.1\n },\n defaultValue: 1.0,\n versionAdded: '1.0.0'\n },\n {\n id: 'Comfy.MaskEditor.UseDominantAxis',\n category: ['Mask Editor', 'BrushAdjustment', 'UseDominantAxis'],\n name: 'Lock brush adjustment to dominant axis',\n tooltip:\n 'When enabled, brush adjustments will only affect size OR hardness based on which direction you move more',\n type: 'boolean',\n defaultValue: true\n }\n ],\n commands: [\n {\n id: 'Comfy.MaskEditor.OpenMaskEditor',\n icon: 'pi pi-pencil',\n label: 'Open Mask Editor for Selected Node',\n function: () => {\n const selectedNodes = app.canvas.selected_nodes\n if (!selectedNodes || Object.keys(selectedNodes).length !== 1) return\n\n const selectedNode = selectedNodes[Object.keys(selectedNodes)[0]]\n openMaskEditor(selectedNode)\n }\n },\n {\n id: 'Comfy.MaskEditor.BrushSize.Increase',\n icon: 'pi pi-plus-circle',\n label: 'Increase Brush Size in MaskEditor',\n function: () => changeBrushSize((old) => _.clamp(old + 2, 1, 250))\n },\n {\n id: 'Comfy.MaskEditor.BrushSize.Decrease',\n icon: 'pi pi-minus-circle',\n label: 'Decrease Brush Size in MaskEditor',\n function: () => changeBrushSize((old) => _.clamp(old - 2, 1, 250))\n },\n {\n id: 'Comfy.MaskEditor.ColorPicker',\n icon: 'pi pi-palette',\n label: 'Open Color Picker in MaskEditor',\n function: () => {\n if (!isOpened()) return\n\n const store = useMaskEditorStore()\n store.colorInput?.click()\n }\n }\n ],\n init() {\n // Set up ComfyApp static methods for plugin compatibility (deprecated)\n ComfyApp.open_maskeditor = openMaskEditorFromClipspace\n\n console.warn(\n '[MaskEditor] ComfyApp.open_maskeditor is deprecated. ' +\n 'Plugins should migrate to using the command system or direct node context menu integration.'\n )\n }\n})\n","import { downloadBlob } from '@/base/common/downloadUtil'\nimport { t } from '@/i18n'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport type { LGraphCanvas } from '@/lib/litegraph/src/litegraph'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { useDialogService } from '@/services/dialogService'\nimport type { ComfyExtension } from '@/types/comfy'\nimport { deserialiseAndCreate } from '@/utils/vintageClipboard'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\nimport { $el, ComfyDialog } from '../../scripts/ui'\nimport { GroupNodeConfig, GroupNodeHandler } from './groupNode'\n\n// Adds the ability to save and add multiple nodes as a template\n// To save:\n// Select multiple nodes (ctrl + drag to select a region or ctrl+click individual nodes)\n// Right click the canvas\n// Save Node Template -> give it a name\n//\n// To add:\n// Right click the canvas\n// Node templates -> click the one to add\n//\n// To delete/rename:\n// Right click the canvas\n// Node templates -> Manage\n//\n// To rearrange:\n// Open the manage dialog and Drag and drop elements using the \"Name:\" label as handle\n\nconst id = 'Comfy.NodeTemplates'\nconst file = 'comfy.templates.json'\n\nclass ManageTemplates extends ComfyDialog {\n // @ts-expect-error fixme ts strict error\n templates: any[]\n draggedEl: HTMLElement | null\n saveVisualCue: number | null\n emptyImg: HTMLImageElement\n importInput: HTMLInputElement\n\n constructor() {\n super()\n this.load().then((v) => {\n this.templates = v\n })\n\n this.element.classList.add('comfy-manage-templates')\n this.draggedEl = null\n this.saveVisualCue = null\n this.emptyImg = new Image()\n this.emptyImg.src =\n 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='\n\n this.importInput = $el('input', {\n type: 'file',\n accept: '.json',\n multiple: true,\n style: { display: 'none' },\n parent: document.body,\n onchange: () => this.importAll()\n }) as HTMLInputElement\n }\n\n override createButtons() {\n const btns = super.createButtons()\n btns[0].textContent = 'Close'\n btns[0].onclick = () => {\n // @ts-expect-error fixme ts strict error\n clearTimeout(this.saveVisualCue)\n this.close()\n }\n btns.unshift(\n $el('button', {\n type: 'button',\n textContent: 'Export',\n onclick: () => this.exportAll()\n })\n )\n btns.unshift(\n $el('button', {\n type: 'button',\n textContent: 'Import',\n onclick: () => {\n this.importInput.click()\n }\n })\n )\n return btns\n }\n\n async load() {\n let templates = []\n const res = await api.getUserData(file)\n if (res.status === 200) {\n try {\n templates = await res.json()\n } catch (error) {}\n } else if (res.status !== 404) {\n console.error(res.status + ' ' + res.statusText)\n }\n return templates ?? []\n }\n\n async store() {\n const templates = JSON.stringify(this.templates, undefined, 4)\n try {\n await api.storeUserData(file, templates, { stringify: false })\n } catch (error) {\n console.error(error)\n // @ts-expect-error fixme ts strict error\n useToastStore().addAlert(error.message)\n }\n }\n\n async importAll() {\n // @ts-expect-error fixme ts strict error\n for (const file of this.importInput.files) {\n if (file.type === 'application/json' || file.name.endsWith('.json')) {\n const reader = new FileReader()\n reader.onload = async () => {\n const importFile = JSON.parse(reader.result as string)\n if (importFile?.templates) {\n for (const template of importFile.templates) {\n if (template?.name && template?.data) {\n this.templates.push(template)\n }\n }\n await this.store()\n }\n }\n await reader.readAsText(file)\n }\n }\n\n // @ts-expect-error fixme ts strict error\n this.importInput.value = null\n\n this.close()\n }\n\n exportAll() {\n if (this.templates.length == 0) {\n useToastStore().addAlert(t('toastMessages.noTemplatesToExport'))\n return\n }\n\n const json = JSON.stringify({ templates: this.templates }, null, 2) // convert the data to a JSON string\n const blob = new Blob([json], { type: 'application/json' })\n downloadBlob('node_templates.json', blob)\n }\n\n override show() {\n // Show list of template names + delete button\n super.show(\n $el(\n 'div',\n {},\n this.templates.flatMap((t, i) => {\n // @ts-expect-error fixme ts strict error\n let nameInput\n return [\n $el(\n 'div',\n {\n dataset: { id: i.toString() },\n className: 'templateManagerRow',\n style: {\n display: 'grid',\n gridTemplateColumns: '1fr auto',\n border: '1px dashed transparent',\n gap: '5px',\n backgroundColor: 'var(--comfy-menu-bg)'\n },\n // @ts-expect-error fixme ts strict error\n ondragstart: (e) => {\n this.draggedEl = e.currentTarget\n e.currentTarget.style.opacity = '0.6'\n e.currentTarget.style.border = '1px dashed yellow'\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setDragImage(this.emptyImg, 0, 0)\n },\n // @ts-expect-error fixme ts strict error\n ondragend: (e) => {\n e.target.style.opacity = '1'\n e.currentTarget.style.border = '1px dashed transparent'\n e.currentTarget.removeAttribute('draggable')\n\n // rearrange the elements\n this.element\n .querySelectorAll('.templateManagerRow')\n // @ts-expect-error fixme ts strict error\n .forEach((el: HTMLElement, i) => {\n // @ts-expect-error fixme ts strict error\n var prev_i = Number.parseInt(el.dataset.id)\n\n if (el == this.draggedEl && prev_i != i) {\n this.templates.splice(\n i,\n 0,\n this.templates.splice(prev_i, 1)[0]\n )\n }\n el.dataset.id = i.toString()\n })\n this.store()\n },\n // @ts-expect-error fixme ts strict error\n ondragover: (e) => {\n e.preventDefault()\n if (e.currentTarget == this.draggedEl) return\n\n let rect = e.currentTarget.getBoundingClientRect()\n if (e.clientY > rect.top + rect.height / 2) {\n e.currentTarget.parentNode.insertBefore(\n this.draggedEl,\n e.currentTarget.nextSibling\n )\n } else {\n e.currentTarget.parentNode.insertBefore(\n this.draggedEl,\n e.currentTarget\n )\n }\n }\n },\n [\n $el(\n 'label',\n {\n textContent: 'Name: ',\n style: {\n cursor: 'grab'\n },\n // @ts-expect-error fixme ts strict error\n onmousedown: (e) => {\n // enable dragging only from the label\n if (e.target.localName == 'label')\n e.currentTarget.parentNode.draggable = 'true'\n }\n },\n [\n $el('input', {\n value: t.name,\n dataset: { name: t.name },\n style: {\n transitionProperty: 'background-color',\n transitionDuration: '0s'\n },\n // @ts-expect-error fixme ts strict error\n onchange: (e) => {\n // @ts-expect-error fixme ts strict error\n clearTimeout(this.saveVisualCue)\n var el = e.target\n var row = el.parentNode.parentNode\n this.templates[row.dataset.id].name =\n el.value.trim() || 'untitled'\n this.store()\n el.style.backgroundColor = 'rgb(40, 95, 40)'\n el.style.transitionDuration = '0s'\n // @ts-expect-error\n // In browser env the return value is number.\n this.saveVisualCue = setTimeout(function () {\n el.style.transitionDuration = '.7s'\n el.style.backgroundColor = 'var(--comfy-input-bg)'\n }, 15)\n },\n // @ts-expect-error fixme ts strict error\n onkeypress: (e) => {\n var el = e.target\n // @ts-expect-error fixme ts strict error\n clearTimeout(this.saveVisualCue)\n el.style.transitionDuration = '0s'\n el.style.backgroundColor = 'var(--comfy-input-bg)'\n },\n $: (el) => (nameInput = el)\n })\n ]\n ),\n $el('div', {}, [\n $el('button', {\n textContent: 'Export',\n style: {\n fontSize: '12px',\n fontWeight: 'normal'\n },\n onclick: () => {\n const json = JSON.stringify({ templates: [t] }, null, 2) // convert the data to a JSON string\n const blob = new Blob([json], {\n type: 'application/json'\n })\n // @ts-expect-error fixme ts strict error\n const name = (nameInput.value || t.name) + '.json'\n downloadBlob(name, blob)\n }\n }),\n $el('button', {\n textContent: 'Delete',\n style: {\n fontSize: '12px',\n color: 'red',\n fontWeight: 'normal'\n },\n // @ts-expect-error fixme ts strict error\n onclick: (e) => {\n const item = e.target.parentNode.parentNode\n item.parentNode.removeChild(item)\n this.templates.splice(item.dataset.id * 1, 1)\n this.store()\n // update the rows index, setTimeout ensures that the list is updated\n var that = this\n setTimeout(function () {\n that.element\n .querySelectorAll('.templateManagerRow')\n // @ts-expect-error fixme ts strict error\n .forEach((el: HTMLElement, i) => {\n el.dataset.id = i.toString()\n })\n }, 0)\n }\n })\n ])\n ]\n )\n ]\n })\n )\n )\n }\n}\n\nconst manage = new ManageTemplates()\n\n// @ts-expect-error fixme ts strict error\nconst clipboardAction = async (cb) => {\n // We use the clipboard functions but dont want to overwrite the current user clipboard\n // Restore it after we've run our callback\n const old = localStorage.getItem('litegrapheditor_clipboard')\n await cb()\n // @ts-expect-error fixme ts strict error\n localStorage.setItem('litegrapheditor_clipboard', old)\n}\n\nconst ext: ComfyExtension = {\n name: id,\n\n getCanvasMenuItems(_canvas: LGraphCanvas): IContextMenuValue[] {\n const items: IContextMenuValue[] = []\n\n // @ts-expect-error fixme ts strict error\n items.push(null)\n items.push({\n content: `Save Selected as Template`,\n disabled: !Object.keys(app.canvas.selected_nodes || {}).length,\n callback: async () => {\n const name = await useDialogService().prompt({\n title: t('nodeTemplates.saveAsTemplate'),\n message: t('nodeTemplates.enterName'),\n defaultValue: ''\n })\n if (!name?.trim()) return\n\n clipboardAction(() => {\n app.canvas.copyToClipboard()\n let data = localStorage.getItem('litegrapheditor_clipboard')\n data = JSON.parse(data || '{}')\n const nodeIds = Object.keys(app.canvas.selected_nodes)\n for (let i = 0; i < nodeIds.length; i++) {\n const node = app.canvas.graph?.getNodeById(nodeIds[i])\n const nodeData = node?.constructor.nodeData\n\n let groupData = GroupNodeHandler.getGroupData(node)\n if (groupData) {\n groupData = groupData.nodeData\n // @ts-expect-error\n if (!data.groupNodes) {\n // @ts-expect-error\n data.groupNodes = {}\n }\n if (nodeData == null) throw new TypeError('nodeData is not set')\n // @ts-expect-error\n data.groupNodes[nodeData.name] = groupData\n // @ts-expect-error\n data.nodes[i].type = nodeData.name\n }\n }\n\n manage.templates.push({\n name,\n data: JSON.stringify(data)\n })\n manage.store()\n })\n }\n })\n\n // Map each template to a menu item\n const subItems = manage.templates.map((t) => {\n return {\n content: t.name,\n callback: () => {\n clipboardAction(async () => {\n const data = JSON.parse(t.data)\n await GroupNodeConfig.registerFromWorkflow(data.groupNodes, {})\n\n // Check for old clipboard format\n if (!data.reroutes) {\n deserialiseAndCreate(t.data, app.canvas)\n } else {\n localStorage.setItem('litegrapheditor_clipboard', t.data)\n app.canvas.pasteFromClipboard()\n }\n })\n }\n }\n })\n\n // @ts-expect-error fixme ts strict error\n subItems.push(null, {\n content: 'Manage',\n callback: () => manage.show()\n })\n\n items.push({\n content: 'Node Templates',\n submenu: {\n options: subItems\n }\n })\n\n return items\n }\n}\n\napp.registerExtension(ext)\n","import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'\nimport { LGraphNode } from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '../../scripts/app'\nimport { ComfyWidgets } from '../../scripts/widgets'\n\n// Node that add notes to your project\n\napp.registerExtension({\n name: 'Comfy.NoteNode',\n registerCustomNodes() {\n class NoteNode extends LGraphNode {\n static override category: string\n static collapsable: boolean\n static title_mode: number\n\n groupcolor = LGraphCanvas.node_colors.yellow.groupcolor\n override isVirtualNode: boolean\n\n constructor(title: string) {\n super(title)\n\n this.color = LGraphCanvas.node_colors.yellow.color\n this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor\n\n if (!this.properties) {\n this.properties = { text: '' }\n }\n ComfyWidgets.STRING(\n this,\n 'text',\n ['STRING', { default: this.properties.text, multiline: true }],\n app\n )\n\n this.serialize_widgets = true\n this.isVirtualNode = true\n }\n }\n\n // Load default visibility\n\n LiteGraph.registerNodeType(\n 'Note',\n Object.assign(NoteNode, {\n title_mode: LiteGraph.NORMAL_TITLE,\n title: 'Note',\n collapsable: true\n })\n )\n\n NoteNode.category = 'utils'\n\n /** Markdown variant of NoteNode */\n class MarkdownNoteNode extends LGraphNode {\n static override title = 'Markdown Note'\n\n groupcolor = LGraphCanvas.node_colors.yellow.groupcolor\n\n constructor(title: string) {\n super(title)\n\n this.color = LGraphCanvas.node_colors.yellow.color\n this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor\n\n if (!this.properties) {\n this.properties = { text: '' }\n }\n ComfyWidgets.MARKDOWN(\n this,\n 'text',\n ['STRING', { default: this.properties.text }],\n app\n )\n\n this.serialize_widgets = true\n this.isVirtualNode = true\n }\n }\n\n LiteGraph.registerNodeType('MarkdownNote', MarkdownNoteNode)\n MarkdownNoteNode.category = 'utils'\n }\n})\n","/*\nPreview Any - original implement from\nhttps://github.com/rgthree/rgthree-comfy/blob/main/py/display_any.py\nupstream requested in https://github.com/Kosinkadink/rfcs/blob/main/rfcs/0000-corenodes.md#preview-nodes\n */\nimport { app } from '@/scripts/app'\nimport { type DOMWidget } from '@/scripts/domWidget'\nimport { ComfyWidgets } from '@/scripts/widgets'\nimport { useExtensionService } from '@/services/extensionService'\n\nuseExtensionService().registerExtension({\n name: 'Comfy.PreviewAny',\n async beforeRegisterNodeDef(nodeType, nodeData) {\n if (nodeData.name === 'PreviewAny') {\n const onNodeCreated = nodeType.prototype.onNodeCreated\n\n nodeType.prototype.onNodeCreated = function () {\n onNodeCreated ? onNodeCreated.apply(this, []) : undefined\n\n const showValueWidget = ComfyWidgets['MARKDOWN'](\n this,\n 'preview',\n ['MARKDOWN', {}],\n app\n ).widget as DOMWidget<HTMLTextAreaElement, string>\n\n const showValueWidgetPlain = ComfyWidgets['STRING'](\n this,\n 'preview',\n ['STRING', { multiline: true }],\n app\n ).widget as DOMWidget<HTMLTextAreaElement, string>\n\n const showAsPlaintextWidget = ComfyWidgets['BOOLEAN'](\n this,\n 'previewMode',\n [\n 'BOOLEAN',\n { label_on: 'Markdown', label_off: 'Plaintext', default: false }\n ],\n app\n )\n\n showAsPlaintextWidget.widget.callback = (value) => {\n showValueWidget.hidden = !value\n showValueWidget.options.hidden = !value\n showValueWidgetPlain.hidden = value\n showValueWidgetPlain.options.hidden = value\n }\n\n showValueWidget.hidden = true\n showValueWidget.options.hidden = true\n showValueWidget.options.read_only = true\n showValueWidget.element.readOnly = true\n showValueWidget.element.disabled = true\n showValueWidget.serialize = false\n\n showValueWidgetPlain.hidden = false\n showValueWidgetPlain.options.hidden = false\n showValueWidgetPlain.options.read_only = true\n showValueWidgetPlain.element.readOnly = true\n showValueWidgetPlain.element.disabled = true\n showValueWidgetPlain.serialize = false\n }\n\n const onExecuted = nodeType.prototype.onExecuted\n\n nodeType.prototype.onExecuted = function (message) {\n onExecuted === null || onExecuted === void 0\n ? void 0\n : onExecuted.apply(this, [message])\n\n const previewWidgets =\n this.widgets?.filter((w) => w.name === 'preview') ?? []\n\n for (const previewWidget of previewWidgets) {\n const text = message.text ?? ''\n previewWidget.value = Array.isArray(text) ? (text[0] ?? '') : text\n }\n }\n }\n }\n})\n","import type { IContextMenuValue } from '@/lib/litegraph/src/litegraph'\nimport {\n LGraphCanvas,\n LGraphNode,\n LiteGraph\n} from '@/lib/litegraph/src/litegraph'\nimport type { ISlotType } from '@/lib/litegraph/src/interfaces'\n\nimport { app } from '../../scripts/app'\nimport { getWidgetConfig, mergeIfValid, setWidgetConfig } from './widgetInputs'\n\n// Node that allows you to redirect connections for cleaner graphs\n\napp.registerExtension({\n name: 'Comfy.RerouteNode',\n registerCustomNodes(app) {\n interface RerouteNode extends LGraphNode {\n __outputType?: string | number\n }\n\n class RerouteNode extends LGraphNode {\n static override category: string | undefined\n static defaultVisibility = false\n\n constructor(title?: string) {\n super(title ?? '')\n if (!this.properties) {\n this.properties = {}\n }\n this.properties.showOutputText = RerouteNode.defaultVisibility\n this.properties.horizontal = false\n\n this.addInput('', '*')\n this.addOutput(this.properties.showOutputText ? '*' : '', '*')\n\n // This node is purely frontend and does not impact the resulting prompt so should not be serialized\n this.isVirtualNode = true\n }\n override onAfterGraphConfigured() {\n requestAnimationFrame(() => {\n this.onConnectionsChange(LiteGraph.INPUT, undefined, true)\n })\n }\n override clone(): LGraphNode | null {\n const cloned = super.clone()\n if (!cloned) return cloned\n cloned.removeOutput(0)\n cloned.addOutput(this.properties.showOutputText ? '*' : '', '*')\n cloned.setSize(cloned.computeSize())\n return cloned\n }\n override onConnectionsChange(\n type: ISlotType,\n _index: number | undefined,\n connected: boolean\n ) {\n const { graph } = this\n if (!graph) return\n if (app.configuringGraph) return\n\n // Prevent multiple connections to different types when we have no input\n if (connected && type === LiteGraph.OUTPUT) {\n // Ignore wildcard nodes as these will be updated to real types\n const types = new Set(\n this.outputs[0].links\n ?.map((l) => graph.links[l]?.type)\n ?.filter((t) => t && t !== '*') ?? []\n )\n if (types.size > 1) {\n const linksToDisconnect = []\n for (const linkId of this.outputs[0].links ?? []) {\n const link = graph.links[linkId]\n linksToDisconnect.push(link)\n }\n linksToDisconnect.pop()\n for (const link of linksToDisconnect) {\n const node = graph.getNodeById(link.target_id)\n node?.disconnectInput(link.target_slot)\n }\n }\n }\n\n // Find root input\n let currentNode: RerouteNode | null = this\n let updateNodes: RerouteNode[] = []\n let inputType = null\n let inputNode = null\n while (currentNode) {\n updateNodes.unshift(currentNode)\n const linkId = currentNode.inputs[0].link\n if (linkId !== null) {\n const link = graph.links[linkId]\n if (!link) return\n const node = graph.getNodeById(link.origin_id)\n if (!node) return\n if (node instanceof RerouteNode) {\n if (node === this) {\n // We've found a circle\n currentNode.disconnectInput(link.target_slot)\n currentNode = null\n } else {\n // Move the previous node\n currentNode = node\n }\n } else {\n // We've found the end\n inputNode = currentNode\n inputType = node.outputs[link.origin_slot]?.type ?? null\n break\n }\n } else {\n // This path has no input node\n currentNode = null\n break\n }\n }\n\n // Find all outputs\n const nodes: RerouteNode[] = [this]\n let outputType = null\n while (nodes.length) {\n currentNode = nodes.pop()!\n const outputs = currentNode.outputs?.[0]?.links ?? []\n for (const linkId of outputs) {\n const link = graph.links[linkId]\n\n // When disconnecting sometimes the link is still registered\n if (!link) continue\n\n const node = graph.getNodeById(link.target_id)\n if (!node) continue\n if (node instanceof RerouteNode) {\n // Follow reroute nodes\n nodes.push(node)\n updateNodes.push(node)\n } else {\n // We've found an output\n const nodeInput = node.inputs[link.target_slot]\n const nodeOutType = nodeInput.type\n const keep =\n !inputType ||\n !nodeOutType ||\n LiteGraph.isValidConnection(inputType, nodeOutType)\n if (!keep) {\n // The output doesnt match our input so disconnect it\n node.disconnectInput(link.target_slot)\n continue\n }\n node.onConnectionsChange?.(\n LiteGraph.INPUT,\n link.target_slot,\n keep,\n link,\n nodeInput\n )\n outputType = node.inputs[link.target_slot].type\n }\n }\n }\n\n const displayType = inputType || outputType || '*'\n const color = LGraphCanvas.link_type_colors[displayType]\n\n let widgetConfig\n let widgetType\n // Update the types of each node\n for (const node of updateNodes) {\n // If we dont have an input type we are always wildcard but we'll show the output type\n // This lets you change the output link to a different type and all nodes will update\n node.outputs[0].type = inputType || '*'\n node.__outputType = displayType\n node.outputs[0].name = node.properties.showOutputText\n ? `${displayType}`\n : ''\n node.setSize(node.computeSize())\n\n for (const l of node.outputs[0].links || []) {\n const link = graph.links[l]\n if (!link) continue\n link.color = color\n\n if (app.configuringGraph) continue\n const targetNode = graph.getNodeById(link.target_id)\n if (!targetNode) continue\n const targetInput = targetNode.inputs?.[link.target_slot]\n if (targetInput?.widget) {\n const config = getWidgetConfig(targetInput)\n if (!widgetConfig) {\n widgetConfig = config[1] ?? {}\n widgetType = config[0]\n }\n\n const merged = mergeIfValid(targetInput, [\n config[0],\n widgetConfig\n ])\n if (merged.customConfig) {\n widgetConfig = merged.customConfig\n }\n }\n }\n }\n\n for (const node of updateNodes) {\n if (widgetConfig && outputType) {\n node.inputs[0].widget = { name: 'value' }\n setWidgetConfig(node.inputs[0], [\n widgetType ?? `${displayType}`,\n widgetConfig\n ])\n } else {\n setWidgetConfig(node.inputs[0], undefined)\n }\n }\n\n if (inputNode?.inputs?.[0]?.link) {\n const link = graph.links[inputNode.inputs[0].link]\n if (link) {\n link.color = color\n }\n }\n }\n\n override getExtraMenuOptions(\n _: unknown,\n options: (IContextMenuValue | null)[]\n ): IContextMenuValue[] {\n options.unshift(\n {\n content:\n (this.properties.showOutputText ? 'Hide' : 'Show') + ' Type',\n callback: () => {\n this.properties.showOutputText = !this.properties.showOutputText\n if (this.properties.showOutputText) {\n this.outputs[0].name = `${this.__outputType || this.outputs[0].type}`\n } else {\n this.outputs[0].name = ''\n }\n this.setSize(this.computeSize())\n app.canvas.setDirty(true, true)\n }\n },\n {\n content:\n (RerouteNode.defaultVisibility ? 'Hide' : 'Show') +\n ' Type By Default',\n callback: () => {\n RerouteNode.setDefaultTextVisibility(\n !RerouteNode.defaultVisibility\n )\n }\n }\n )\n return []\n }\n override computeSize(): [number, number] {\n return [\n this.properties.showOutputText && this.outputs && this.outputs.length\n ? Math.max(\n 75,\n LiteGraph.NODE_TEXT_SIZE * this.outputs[0].name.length * 0.6 +\n 40\n )\n : 75,\n 26\n ]\n }\n\n static setDefaultTextVisibility(visible: boolean) {\n RerouteNode.defaultVisibility = visible\n if (visible) {\n localStorage['Comfy.RerouteNode.DefaultVisibility'] = 'true'\n } else {\n delete localStorage['Comfy.RerouteNode.DefaultVisibility']\n }\n }\n }\n\n // Load default visibility\n RerouteNode.setDefaultTextVisibility(\n !!localStorage['Comfy.RerouteNode.DefaultVisibility']\n )\n\n LiteGraph.registerNodeType(\n 'Reroute',\n Object.assign(RerouteNode, {\n title_mode: LiteGraph.NO_TITLE,\n title: 'Reroute',\n collapsable: false\n })\n )\n\n RerouteNode.category = 'utils'\n }\n})\n","import { applyTextReplacements } from '@/utils/searchAndReplace'\n\nimport { app } from '../../scripts/app'\n\nconst saveNodeTypes = new Set([\n 'SaveImage',\n 'SaveVideo',\n 'SaveAnimatedWEBP',\n 'SaveWEBM',\n 'SaveAudio',\n 'SaveGLB',\n 'SaveAnimatedPNG',\n 'CLIPSave',\n 'VAESave',\n 'ModelSave',\n 'LoraSave',\n 'SaveLatent'\n])\n\n// Use widget values and dates in output filenames\n\napp.registerExtension({\n name: 'Comfy.SaveImageExtraOutput',\n async beforeRegisterNodeDef(nodeType, nodeData, app) {\n if (saveNodeTypes.has(nodeData.name)) {\n const onNodeCreated = nodeType.prototype.onNodeCreated\n // When the SaveImage node is created we want to override the serialization of the output name widget to run our S&R\n nodeType.prototype.onNodeCreated = function () {\n const r = onNodeCreated\n ? // @ts-expect-error fixme ts strict error\n onNodeCreated.apply(this, arguments)\n : undefined\n\n // @ts-expect-error fixme ts strict error\n const widget = this.widgets.find((w) => w.name === 'filename_prefix')\n // @ts-expect-error fixme ts strict error\n widget.serializeValue = () => {\n // @ts-expect-error fixme ts strict error\n return applyTextReplacements(app.graph, widget.value)\n }\n\n return r\n }\n } else {\n // When any other node is created add a property to alias the node\n const onNodeCreated = nodeType.prototype.onNodeCreated\n nodeType.prototype.onNodeCreated = function () {\n const r = onNodeCreated\n ? // @ts-expect-error fixme ts strict error\n onNodeCreated.apply(this, arguments)\n : undefined\n\n if (!this.properties || !('Node name for S&R' in this.properties)) {\n this.addProperty('Node name for S&R', this.constructor.type, 'string')\n }\n\n return r\n }\n }\n }\n})\n","import { nextTick } from 'vue'\n\nimport Load3D from '@/components/load3d/Load3D.vue'\nimport { useLoad3d } from '@/composables/useLoad3d'\nimport { createExportMenuItems } from '@/extensions/core/load3d/exportMenuHelper'\nimport Load3DConfiguration from '@/extensions/core/load3d/Load3DConfiguration'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'\nimport { type CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport { ComponentWidgetImpl, addWidget } from '@/scripts/domWidget'\nimport { useExtensionService } from '@/services/extensionService'\nimport { useLoad3dService } from '@/services/load3dService'\n\nconst inputSpec: CustomInputSpec = {\n name: 'image',\n type: 'Preview3D',\n isPreview: true\n}\n\nuseExtensionService().registerExtension({\n name: 'Comfy.SaveGLB',\n\n async beforeRegisterNodeDef(_nodeType, nodeData) {\n if ('SaveGLB' === nodeData.name) {\n // @ts-expect-error InputSpec is not typed correctly\n nodeData.input.required.image = ['PREVIEW_3D']\n }\n },\n\n getCustomWidgets() {\n return {\n PREVIEW_3D(node) {\n const widget = new ComponentWidgetImpl({\n node,\n name: inputSpec.name,\n component: Load3D,\n inputSpec,\n options: {}\n })\n\n widget.type = 'load3D'\n\n addWidget(node, widget)\n\n return { widget }\n }\n }\n },\n\n getNodeMenuItems(node: LGraphNode): (IContextMenuValue | null)[] {\n // Only show menu items for SaveGLB nodes\n if (node.constructor.comfyClass !== 'SaveGLB') return []\n\n const load3d = useLoad3dService().getLoad3d(node)\n if (!load3d) return []\n\n if (load3d.isSplatModel()) return []\n\n return createExportMenuItems(load3d)\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'SaveGLB') return\n\n const [oldWidth, oldHeight] = node.size\n\n node.setSize([Math.max(oldWidth, 400), Math.max(oldHeight, 550)])\n\n await nextTick()\n\n const onExecuted = node.onExecuted\n\n node.onExecuted = function (message: any) {\n onExecuted?.apply(this, arguments as any)\n\n const fileInfo = message['3d'][0]\n\n useLoad3d(node).waitForLoad3d((load3d) => {\n const modelWidget = node.widgets?.find((w) => w.name === 'image')\n\n if (load3d && modelWidget) {\n const filePath = fileInfo['subfolder'] + '/' + fileInfo['filename']\n\n modelWidget.value = filePath\n\n const config = new Load3DConfiguration(load3d, node.properties)\n\n config.configureForSaveMesh(fileInfo['type'], filePath)\n }\n })\n }\n }\n})\n","import { type LGraphCanvas, createBounds } from '@/lib/litegraph/src/litegraph'\nimport { app } from '@/scripts/app'\n\n/**\n * Draws a dashed border around selected items that maintains constant pixel size\n * regardless of zoom level, similar to the DOM selection overlay.\n */\nfunction drawSelectionBorder(\n ctx: CanvasRenderingContext2D,\n canvas: LGraphCanvas\n) {\n const selectedItems = canvas.selectedItems\n\n // Only draw if multiple items selected\n if (selectedItems.size <= 1) return\n\n // Use the same bounds calculation as the toolbox\n const bounds = createBounds(selectedItems, 10)\n if (!bounds) return\n\n const [x, y, width, height] = bounds\n\n // Save context state\n ctx.save()\n\n // Set up dashed line style that doesn't scale with zoom\n const borderWidth = 2 / canvas.ds.scale // Constant 2px regardless of zoom\n ctx.lineWidth = borderWidth\n ctx.strokeStyle =\n getComputedStyle(document.documentElement)\n .getPropertyValue('--border-color')\n .trim() || '#ffffff66'\n\n // Create dash pattern that maintains visual size\n const dashSize = 5 / canvas.ds.scale\n ctx.setLineDash([dashSize, dashSize])\n\n // Draw the border using the bounds directly\n ctx.beginPath()\n ctx.roundRect(x, y, width, height, 8 / canvas.ds.scale)\n ctx.stroke()\n\n // Restore context\n ctx.restore()\n}\n\n/**\n * Extension that adds a dashed selection border for multiple selected nodes\n */\nconst ext = {\n name: 'Comfy.SelectionBorder',\n\n async init() {\n // Hook into the canvas drawing\n const originalDrawForeground = app.canvas.onDrawForeground\n\n app.canvas.onDrawForeground = function (\n ctx: CanvasRenderingContext2D,\n visibleArea: any\n ) {\n // Call original if it exists\n originalDrawForeground?.call(this, ctx, visibleArea)\n\n // Draw our selection border\n drawSelectionBorder(ctx, app.canvas)\n }\n }\n}\n\napp.registerExtension(ext)\n","import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '@/scripts/app'\n\nlet touchZooming = false\nlet touchCount = 0\n\napp.registerExtension({\n name: 'Comfy.SimpleTouchSupport',\n setup() {\n let touchDist: number | null = null\n let touchTime: Date | null = null\n let lastTouch: { clientX: number; clientY: number } | null = null\n let lastScale: number | null = null\n function getMultiTouchPos(e: TouchEvent) {\n return Math.hypot(\n e.touches[0].clientX - e.touches[1].clientX,\n e.touches[0].clientY - e.touches[1].clientY\n )\n }\n\n function getMultiTouchCenter(e: TouchEvent) {\n return {\n clientX: (e.touches[0].clientX + e.touches[1].clientX) / 2,\n clientY: (e.touches[0].clientY + e.touches[1].clientY) / 2\n }\n }\n\n app.canvasEl.parentElement?.addEventListener(\n 'touchstart',\n (e: TouchEvent) => {\n touchCount += e.changedTouches.length\n\n lastTouch = null\n lastScale = null\n if (e.touches?.length === 1) {\n // Store start time for press+hold for context menu\n touchTime = new Date()\n lastTouch = e.touches[0]\n } else {\n touchTime = null\n if (e.touches?.length === 2) {\n // Store center pos for zoom\n lastScale = app.canvas.ds.scale\n lastTouch = getMultiTouchCenter(e)\n\n touchDist = getMultiTouchPos(e)\n app.canvas.pointer.isDown = false\n }\n }\n },\n true\n )\n\n app.canvasEl.parentElement?.addEventListener(\n 'touchend',\n (e: TouchEvent) => {\n touchCount -= e.changedTouches.length\n\n if (e.touches?.length !== 1) touchZooming = false\n if (touchTime && !e.touches?.length) {\n if (new Date().getTime() - touchTime.getTime() > 600) {\n if (e.target === app.canvasEl) {\n const touch = {\n button: 2, // Right click\n clientX: e.changedTouches[0].clientX,\n clientY: e.changedTouches[0].clientY,\n pointerId: 1, // changedTouches' id is 0, set it to any number\n isPrimary: true // changedTouches' isPrimary is false, so set it to true\n }\n // context menu info set in 'pointerdown' event\n app.canvasEl.dispatchEvent(new PointerEvent('pointerdown', touch))\n // then, context menu open after 'pointerup' event\n setTimeout(() => {\n app.canvasEl.dispatchEvent(new PointerEvent('pointerup', touch))\n })\n e.preventDefault()\n }\n }\n touchTime = null\n }\n }\n )\n\n const resetTouchState = () => {\n touchCount = 0\n touchZooming = false\n touchTime = null\n lastTouch = null\n lastScale = null\n touchDist = null\n }\n\n // Reset touch state when page loses visibility (e.g., switching apps on iPad)\n // This prevents touchCount from getting stuck when touchend events are missed\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) {\n resetTouchState()\n }\n })\n\n // Also handle touchcancel which fires when touch is interrupted\n app.canvasEl.parentElement?.addEventListener('touchcancel', resetTouchState)\n\n app.canvasEl.parentElement?.addEventListener(\n 'touchmove',\n (e) => {\n // make a threshold for touchmove to prevent clear touchTime for long press\n if (touchTime && lastTouch && e.touches?.length === 1) {\n const onlyTouch = e.touches[0]\n const deltaX = onlyTouch.clientX - lastTouch.clientX\n const deltaY = onlyTouch.clientY - lastTouch.clientY\n if (deltaX * deltaX + deltaY * deltaY > 30) {\n touchTime = null\n }\n }\n if (e.touches?.length === 2 && lastTouch && !e.ctrlKey && !e.shiftKey) {\n e.preventDefault() // Prevent browser from zooming when two textareas are touched\n app.canvas.pointer.isDown = false\n touchZooming = true\n\n LiteGraph.closeAllContextMenus(window)\n // @ts-expect-error\n app.canvas.search_box?.close()\n const newTouchDist = getMultiTouchPos(e)\n\n const center = getMultiTouchCenter(e)\n\n if (lastScale === null || touchDist === null) return\n let scale = (lastScale * newTouchDist) / touchDist\n\n const newX = (center.clientX - lastTouch.clientX) / scale\n const newY = (center.clientY - lastTouch.clientY) / scale\n\n // Code from LiteGraph\n if (scale < app.canvas.ds.min_scale) {\n scale = app.canvas.ds.min_scale\n } else if (scale > app.canvas.ds.max_scale) {\n scale = app.canvas.ds.max_scale\n }\n\n const oldScale = app.canvas.ds.scale\n\n app.canvas.ds.scale = scale\n\n // Code from LiteGraph\n if (Math.abs(app.canvas.ds.scale - 1) < 0.01) {\n app.canvas.ds.scale = 1\n }\n\n const newScale = app.canvas.ds.scale\n\n const convertScaleToOffset = (scale: number) => [\n center.clientX / scale - app.canvas.ds.offset[0],\n center.clientY / scale - app.canvas.ds.offset[1]\n ]\n var oldCenter = convertScaleToOffset(oldScale)\n var newCenter = convertScaleToOffset(newScale)\n\n app.canvas.ds.offset[0] += newX + newCenter[0] - oldCenter[0]\n app.canvas.ds.offset[1] += newY + newCenter[1] - oldCenter[1]\n\n lastTouch.clientX = center.clientX\n lastTouch.clientY = center.clientY\n\n app.canvas.setDirty(true, true)\n }\n },\n true\n )\n }\n})\n\nconst processMouseDown = LGraphCanvas.prototype.processMouseDown\nLGraphCanvas.prototype.processMouseDown = function (e: PointerEvent) {\n if (touchZooming || touchCount) {\n return\n }\n app.canvas.pointer.isDown = false // Prevent context menu from opening on second tap\n return processMouseDown.apply(this, [e])\n}\n\nconst processMouseMove = LGraphCanvas.prototype.processMouseMove\nLGraphCanvas.prototype.processMouseMove = function (e: PointerEvent) {\n if (touchZooming || touchCount > 1) {\n return\n }\n return processMouseMove.apply(this, [e])\n}\n","import { LiteGraph } from '@/lib/litegraph/src/litegraph'\n\nimport { app } from '../../scripts/app'\nimport { ComfyWidgets } from '../../scripts/widgets'\n\n// Adds defaults for quickly adding nodes with middle click on the input/output\n\napp.registerExtension({\n name: 'Comfy.SlotDefaults',\n suggestionsNumber: null,\n init() {\n LiteGraph.search_filter_enabled = true\n LiteGraph.middle_click_slot_add_default_node = true\n this.suggestionsNumber = app.ui.settings.addSetting({\n id: 'Comfy.NodeSuggestions.number',\n category: ['Comfy', 'Node Search Box', 'NodeSuggestions'],\n name: 'Number of nodes suggestions',\n tooltip: 'Only for litegraph searchbox/context menu',\n type: 'slider',\n attrs: {\n min: 1,\n max: 100,\n step: 1\n },\n defaultValue: 5,\n onChange: (newVal) => {\n this.setDefaults(newVal)\n }\n })\n },\n slot_types_default_out: {},\n slot_types_default_in: {},\n async beforeRegisterNodeDef(nodeType, nodeData) {\n var nodeId = nodeData.name\n const inputs = nodeData['input']?.['required'] //only show required inputs to reduce the mess also not logical to create node with optional inputs\n for (const inputKey in inputs) {\n var input = inputs[inputKey]\n if (typeof input[0] !== 'string') continue\n\n var type = input[0]\n if (type in ComfyWidgets) {\n var customProperties = input[1]\n if (!customProperties?.forceInput) continue //ignore widgets that don't force input\n }\n\n if (!(type in this.slot_types_default_out)) {\n this.slot_types_default_out[type] = ['Reroute']\n }\n if (this.slot_types_default_out[type].includes(nodeId)) continue\n this.slot_types_default_out[type].push(nodeId)\n\n // Input types have to be stored as lower case\n // Store each node that can handle this input type\n const lowerType = type.toLocaleLowerCase()\n if (!(lowerType in LiteGraph.registered_slot_in_types)) {\n LiteGraph.registered_slot_in_types[lowerType] = { nodes: [] }\n }\n LiteGraph.registered_slot_in_types[lowerType].nodes.push(\n // @ts-expect-error ComfyNode\n nodeType.comfyClass\n )\n }\n\n var outputs = nodeData['output'] ?? []\n for (const el of outputs) {\n const type = el as string\n if (!(type in this.slot_types_default_in)) {\n this.slot_types_default_in[type] = ['Reroute']\n }\n\n if (this.slot_types_default_in[type].includes(nodeId)) continue\n this.slot_types_default_in[type].push(nodeId)\n\n // Store each node that can handle this output type\n if (!(type in LiteGraph.registered_slot_out_types)) {\n LiteGraph.registered_slot_out_types[type] = { nodes: [] }\n }\n // @ts-expect-error ComfyNode\n LiteGraph.registered_slot_out_types[type].nodes.push(nodeType.comfyClass)\n\n if (!LiteGraph.slot_types_out.includes(type)) {\n LiteGraph.slot_types_out.push(type)\n }\n }\n\n var maxNum = this.suggestionsNumber.value\n this.setDefaults(maxNum)\n },\n setDefaults(maxNum?: number | null) {\n LiteGraph.slot_types_default_out = {}\n LiteGraph.slot_types_default_in = {}\n\n for (const type in this.slot_types_default_out) {\n LiteGraph.slot_types_default_out[type] = this.slot_types_default_out[\n type\n ].slice(0, maxNum)\n }\n for (const type in this.slot_types_default_in) {\n LiteGraph.slot_types_default_in[type] = this.slot_types_default_in[\n type\n ].slice(0, maxNum)\n }\n }\n})\n","import { MediaRecorder as ExtendableMediaRecorder } from 'extendable-media-recorder'\n\nimport { useChainCallback } from '@/composables/functional/useChainCallback'\nimport { useNodeDragAndDrop } from '@/composables/node/useNodeDragAndDrop'\nimport { useNodeFileInput } from '@/composables/node/useNodeFileInput'\nimport { useNodePaste } from '@/composables/node/useNodePaste'\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/litegraph'\nimport type {\n IBaseWidget,\n IStringWidget\n} from '@/lib/litegraph/src/types/widgets'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport {\n getResourceURL,\n splitFilePath\n} from '@/renderer/extensions/vueNodes/widgets/utils/audioUtils'\nimport type { ComfyNodeDef } from '@/schemas/nodeDefSchema'\nimport type { DOMWidget } from '@/scripts/domWidget'\nimport { useAudioService } from '@/services/audioService'\nimport { type NodeLocatorId } from '@/types'\nimport { getNodeByLocatorId } from '@/utils/graphTraversalUtil'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\n\nasync function uploadFile(\n audioWidget: IStringWidget,\n audioUIWidget: DOMWidget<HTMLAudioElement, string>,\n file: File,\n updateNode: boolean,\n pasted: boolean = false\n) {\n try {\n // Wrap file in formdata so it includes filename\n const body = new FormData()\n body.append('image', file)\n if (pasted) body.append('subfolder', 'pasted')\n const resp = await api.fetchApi('/upload/image', {\n method: 'POST',\n body\n })\n\n if (resp.status === 200) {\n const data = await resp.json()\n // Add the file to the dropdown list and update the widget value\n let path = data.name\n if (data.subfolder) path = data.subfolder + '/' + path\n\n // @ts-expect-error fixme ts strict error\n if (!audioWidget.options.values.includes(path)) {\n // @ts-expect-error fixme ts strict error\n audioWidget.options.values.push(path)\n }\n\n if (updateNode) {\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(...splitFilePath(path))\n )\n audioWidget.value = path\n\n // Manually trigger the callback to update VueNodes\n audioWidget.callback?.(path)\n }\n } else {\n useToastStore().addAlert(resp.status + ' - ' + resp.statusText)\n }\n } catch (error) {\n // @ts-expect-error fixme ts strict error\n useToastStore().addAlert(error)\n }\n}\n\n// AudioWidget MUST be registered first, as AUDIOUPLOAD depends on AUDIO_UI to be\n// present.\napp.registerExtension({\n name: 'Comfy.AudioWidget',\n async beforeRegisterNodeDef(nodeType, nodeData) {\n if (\n [\n 'LoadAudio',\n 'SaveAudio',\n 'PreviewAudio',\n 'SaveAudioMP3',\n 'SaveAudioOpus'\n ].includes(\n // @ts-expect-error fixme ts strict error\n nodeType.prototype.comfyClass\n )\n ) {\n // @ts-expect-error fixme ts strict error\n nodeData.input.required.audioUI = ['AUDIO_UI', {}]\n }\n },\n getCustomWidgets() {\n return {\n AUDIO_UI(node: LGraphNode, inputName: string) {\n const audio = document.createElement('audio')\n audio.controls = true\n audio.classList.add('comfy-audio')\n audio.setAttribute('name', 'media')\n\n const audioUIWidget: DOMWidget<HTMLAudioElement, string> =\n node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)\n audioUIWidget.serialize = false\n const { nodeData } = node.constructor\n if (nodeData == null) throw new TypeError('nodeData is null')\n\n const isOutputNode = nodeData.output_node\n if (isOutputNode) {\n // Hide the audio widget when there is no audio initially.\n audioUIWidget.element.classList.add('empty-audio-widget')\n // Populate the audio widget UI on node execution.\n const onExecuted = node.onExecuted\n node.onExecuted = function (message: any) {\n // @ts-expect-error fixme ts strict error\n onExecuted?.apply(this, arguments)\n const audios = message.audio\n if (!audios) return\n const audio = audios[0]\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(audio.subfolder, audio.filename, audio.type)\n )\n audioUIWidget.element.classList.remove('empty-audio-widget')\n }\n }\n\n audioUIWidget.onRemove = useChainCallback(\n audioUIWidget.onRemove,\n () => {\n if (!audioUIWidget.element) return\n audioUIWidget.element.pause()\n audioUIWidget.element.src = ''\n audioUIWidget.element.remove()\n }\n )\n\n return { widget: audioUIWidget }\n }\n }\n },\n onNodeOutputsUpdated(nodeOutputs: Record<NodeLocatorId, any>) {\n for (const [nodeLocatorId, output] of Object.entries(nodeOutputs)) {\n if ('audio' in output) {\n const node = getNodeByLocatorId(app.rootGraph, nodeLocatorId)\n if (!node) continue\n\n // @ts-expect-error fixme ts strict error\n const audioUIWidget = node.widgets.find(\n (w) => w.name === 'audioUI'\n ) as unknown as DOMWidget<HTMLAudioElement, string>\n const audio = output.audio[0]\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(audio.subfolder, audio.filename, audio.type)\n )\n audioUIWidget.element.classList.remove('empty-audio-widget')\n }\n }\n }\n})\n\napp.registerExtension({\n name: 'Comfy.UploadAudio',\n async beforeRegisterNodeDef(_nodeType, nodeData: ComfyNodeDef) {\n if (nodeData?.input?.required?.audio?.[1]?.audio_upload === true) {\n nodeData.input.required.upload = ['AUDIOUPLOAD', {}]\n }\n },\n getCustomWidgets() {\n return {\n AUDIOUPLOAD(node, inputName: string) {\n // The widget that allows user to select file.\n // @ts-expect-error fixme ts strict error\n const audioWidget = node.widgets.find(\n (w) => w.name === 'audio'\n ) as IStringWidget\n // @ts-expect-error fixme ts strict error\n const audioUIWidget = node.widgets.find(\n (w) => w.name === 'audioUI'\n ) as unknown as DOMWidget<HTMLAudioElement, string>\n audioUIWidget.options.canvasOnly = true\n\n const onAudioWidgetUpdate = () => {\n if (typeof audioWidget.value !== 'string') return\n audioUIWidget.element.src = api.apiURL(\n getResourceURL(...splitFilePath(audioWidget.value))\n )\n }\n // Initially load default audio file to audioUIWidget.\n if (audioWidget.value) {\n onAudioWidgetUpdate()\n }\n audioWidget.callback = onAudioWidgetUpdate\n\n // Load saved audio file widget values if restoring from workflow\n const onGraphConfigured = node.onGraphConfigured\n node.onGraphConfigured = function () {\n // @ts-expect-error fixme ts strict error\n onGraphConfigured?.apply(this, arguments)\n if (audioWidget.value) {\n onAudioWidgetUpdate()\n }\n }\n\n const handleUpload = async (files: File[]) => {\n if (files?.length) {\n uploadFile(audioWidget, audioUIWidget, files[0], true)\n }\n return files\n }\n\n const isAudioFile = (file: File) => file.type.startsWith('audio/')\n\n const { openFileSelection } = useNodeFileInput(node, {\n accept: 'audio/*',\n onSelect: handleUpload\n })\n\n // The widget to pop up the upload dialog.\n const uploadWidget = node.addWidget(\n 'button',\n inputName,\n '',\n openFileSelection,\n { serialize: false, canvasOnly: true }\n )\n uploadWidget.label = t('g.choose_file_to_upload')\n\n useNodeDragAndDrop(node, {\n fileFilter: isAudioFile,\n onDrop: handleUpload\n })\n\n useNodePaste(node, {\n fileFilter: isAudioFile,\n onPaste: handleUpload\n })\n\n node.previewMediaType = 'audio'\n\n return { widget: uploadWidget }\n }\n }\n }\n})\n\napp.registerExtension({\n name: 'Comfy.RecordAudio',\n\n getCustomWidgets() {\n return {\n AUDIO_RECORD(node, inputName: string) {\n const audio = document.createElement('audio')\n audio.controls = true\n audio.classList.add('comfy-audio')\n audio.setAttribute('name', 'media')\n const audioUIWidget: DOMWidget<HTMLAudioElement, string> =\n node.addDOMWidget(inputName, /* name=*/ 'audioUI', audio)\n audioUIWidget.options.canvasOnly = false\n\n let mediaRecorder: MediaRecorder | null = null\n let isRecording = false\n let audioChunks: Blob[] = []\n let currentStream: MediaStream | null = null\n let recordWidget: IBaseWidget | null = null\n\n let stopPromise: Promise<void> | null = null\n let stopResolve: (() => void) | null = null\n\n audioUIWidget.serializeValue = async () => {\n if (isRecording && mediaRecorder) {\n stopPromise = new Promise((resolve) => {\n stopResolve = resolve\n })\n\n mediaRecorder.stop()\n\n await stopPromise\n }\n\n const audioSrc = audioUIWidget.element.src\n\n if (!audioSrc) {\n useToastStore().addAlert(t('g.noAudioRecorded'))\n return ''\n }\n\n const blob = await fetch(audioSrc).then((r) => r.blob())\n\n return await useAudioService().convertBlobToFileAndSubmit(blob)\n }\n\n recordWidget = node.addWidget(\n 'button',\n inputName,\n '',\n async () => {\n if (!isRecording) {\n try {\n currentStream = await navigator.mediaDevices.getUserMedia({\n audio: true\n })\n\n mediaRecorder = new ExtendableMediaRecorder(currentStream, {\n mimeType: 'audio/wav'\n }) as unknown as MediaRecorder\n\n audioChunks = []\n\n mediaRecorder.ondataavailable = (event) => {\n audioChunks.push(event.data)\n }\n\n mediaRecorder.onstop = async () => {\n const audioBlob = new Blob(audioChunks, { type: 'audio/wav' })\n\n useAudioService().stopAllTracks(currentStream)\n\n if (\n audioUIWidget.element.src &&\n audioUIWidget.element.src.startsWith('blob:')\n ) {\n URL.revokeObjectURL(audioUIWidget.element.src)\n }\n\n audioUIWidget.element.src = URL.createObjectURL(audioBlob)\n\n isRecording = false\n\n if (recordWidget) {\n recordWidget.label = t('g.startRecording')\n }\n\n if (stopResolve) {\n stopResolve()\n stopResolve = null\n stopPromise = null\n }\n }\n\n mediaRecorder.onerror = (event) => {\n console.error('MediaRecorder error:', event)\n useAudioService().stopAllTracks(currentStream)\n isRecording = false\n\n if (recordWidget) {\n recordWidget.label = t('g.startRecording')\n }\n\n if (stopResolve) {\n stopResolve()\n stopResolve = null\n stopPromise = null\n }\n }\n\n mediaRecorder.start()\n isRecording = true\n if (recordWidget) {\n recordWidget.label = t('g.stopRecording')\n }\n } catch (err) {\n console.error('Error accessing microphone:', err)\n useToastStore().addAlert(t('g.micPermissionDenied'))\n\n if (mediaRecorder) {\n try {\n mediaRecorder.stop()\n } catch {}\n }\n useAudioService().stopAllTracks(currentStream)\n currentStream = null\n isRecording = false\n if (recordWidget) {\n recordWidget.label = t('g.startRecording')\n }\n }\n } else if (mediaRecorder && isRecording) {\n mediaRecorder.stop()\n }\n },\n { serialize: false, canvasOnly: false }\n )\n\n recordWidget.label = t('g.startRecording')\n // Override the type for Vue rendering while keeping 'button' for LiteGraph\n recordWidget.type = 'audiorecord'\n\n const originalOnRemoved = node.onRemoved\n node.onRemoved = function () {\n if (isRecording && mediaRecorder) {\n mediaRecorder.stop()\n }\n useAudioService().stopAllTracks(currentStream)\n if (audioUIWidget.element.src?.startsWith('blob:')) {\n URL.revokeObjectURL(audioUIWidget.element.src)\n }\n originalOnRemoved?.call(this)\n }\n\n return { widget: recordWidget }\n }\n }\n },\n\n async nodeCreated(node) {\n if (node.constructor.comfyClass !== 'RecordAudio') return\n\n await useAudioService().registerWavEncoder()\n }\n})\n","import {\n type ComfyNodeDef,\n type InputSpec,\n isComboInputSpecV1\n} from '@/schemas/nodeDefSchema'\n\nimport { app } from '../../scripts/app'\n\n// Adds an upload button to the nodes\n\nconst isMediaUploadComboInput = (inputSpec: InputSpec) => {\n const [inputName, inputOptions] = inputSpec\n if (!inputOptions) return false\n\n const isUploadInput =\n inputOptions['image_upload'] === true ||\n inputOptions['video_upload'] === true ||\n inputOptions['animated_image_upload'] === true\n\n return (\n isUploadInput && (isComboInputSpecV1(inputSpec) || inputName === 'COMBO')\n )\n}\n\nconst createUploadInput = (\n imageInputName: string,\n imageInputOptions: InputSpec\n): InputSpec => [\n 'IMAGEUPLOAD',\n {\n ...imageInputOptions[1],\n imageInputName\n }\n]\n\napp.registerExtension({\n name: 'Comfy.UploadImage',\n beforeRegisterNodeDef(_nodeType, nodeData: ComfyNodeDef) {\n const { input } = nodeData ?? {}\n const { required } = input ?? {}\n if (!required) return\n\n const found = Object.entries(required).find(([_, input]) =>\n isMediaUploadComboInput(input)\n )\n\n // If media combo input found, attach upload input\n if (found) {\n const [inputName, inputSpec] = found\n required.upload = createUploadInput(inputName, inputSpec)\n }\n }\n})\n","import { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\n\nimport { api } from '../../scripts/api'\nimport { app } from '../../scripts/app'\n\nconst WEBCAM_READY = Symbol()\n\napp.registerExtension({\n name: 'Comfy.WebcamCapture',\n getCustomWidgets() {\n return {\n WEBCAM(node, inputName) {\n // @ts-expect-error fixme ts strict error\n let res\n // @ts-expect-error fixme ts strict error\n node[WEBCAM_READY] = new Promise((resolve) => (res = resolve))\n\n const container = document.createElement('div')\n container.style.background = 'rgba(0,0,0,0.25)'\n container.style.textAlign = 'center'\n\n const video = document.createElement('video')\n video.style.height = video.style.width = '100%'\n\n const loadVideo = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: false\n })\n container.replaceChildren(video)\n\n // @ts-expect-error fixme ts strict error\n setTimeout(() => res(video), 500) // Fallback as loadedmetadata doesnt fire sometimes?\n // @ts-expect-error fixme ts strict error\n video.addEventListener('loadedmetadata', () => res(video), false)\n video.srcObject = stream\n video.play()\n } catch (error) {\n const label = document.createElement('div')\n label.style.color = 'red'\n label.style.overflow = 'auto'\n label.style.maxHeight = '100%'\n label.style.whiteSpace = 'pre-wrap'\n\n if (window.isSecureContext) {\n label.textContent =\n 'Unable to load webcam, please ensure access is granted:\\n' +\n // @ts-expect-error fixme ts strict error\n error.message\n } else {\n label.textContent =\n 'Unable to load webcam. A secure context is required, if you are not accessing ComfyUI on localhost (127.0.0.1) you will have to enable TLS (https)\\n\\n' +\n // @ts-expect-error fixme ts strict error\n error.message\n }\n\n container.replaceChildren(label)\n }\n }\n\n loadVideo()\n\n return { widget: node.addDOMWidget(inputName, 'WEBCAM', container) }\n }\n }\n },\n nodeCreated(node) {\n if ((node.type, node.constructor.comfyClass !== 'WebcamCapture')) return\n\n // @ts-expect-error fixme ts strict error\n let video\n // @ts-expect-error fixme ts strict error\n const camera = node.widgets.find((w) => w.name === 'image')\n // @ts-expect-error fixme ts strict error\n const w = node.widgets.find((w) => w.name === 'width')\n // @ts-expect-error fixme ts strict error\n const h = node.widgets.find((w) => w.name === 'height')\n // @ts-expect-error fixme ts strict error\n const captureOnQueue = node.widgets.find(\n (w) => w.name === 'capture_on_queue'\n )\n\n const canvas = document.createElement('canvas')\n\n const capture = () => {\n // @ts-expect-error widget value type narrow down\n canvas.width = w.value\n // @ts-expect-error widget value type narrow down\n canvas.height = h.value\n const ctx = canvas.getContext('2d')\n // @ts-expect-error widget value type narrow down\n ctx.drawImage(video, 0, 0, w.value, h.value)\n const data = canvas.toDataURL('image/png')\n\n const img = new Image()\n img.onload = () => {\n node.imgs = [img]\n app.canvas.setDirty(true)\n }\n img.src = data\n }\n\n const btn = node.addWidget(\n 'button',\n 'waiting for camera...',\n 'capture',\n capture,\n { canvasOnly: true }\n )\n btn.disabled = true\n btn.serializeValue = () => undefined\n\n // @ts-expect-error fixme ts strict error\n camera.serializeValue = async () => {\n // @ts-expect-error fixme ts strict error\n if (captureOnQueue.value) {\n capture()\n } else if (!node.imgs?.length) {\n const err = `No webcam image captured`\n useToastStore().addAlert(err)\n throw new Error(err)\n }\n\n // Upload image to temp storage\n // @ts-expect-error fixme ts strict error\n const blob = await new Promise<Blob>((r) => canvas.toBlob(r))\n const name = `${+new Date()}.png`\n const file = new File([blob], name)\n const body = new FormData()\n body.append('image', file)\n body.append('subfolder', 'webcam')\n body.append('type', 'temp')\n const resp = await api.fetchApi('/upload/image', {\n method: 'POST',\n body\n })\n if (resp.status !== 200) {\n const err = `Error uploading camera image: ${resp.status} - ${resp.statusText}`\n useToastStore().addAlert(err)\n throw new Error(err)\n }\n return `webcam/${name} [temp]`\n }\n\n // @ts-expect-error fixme ts strict error\n node[WEBCAM_READY].then((v) => {\n video = v\n // If width isn't specified then use video output resolution\n // @ts-expect-error fixme ts strict error\n if (!w.value) {\n // @ts-expect-error fixme ts strict error\n w.value = video.videoWidth || 640\n // @ts-expect-error fixme ts strict error\n h.value = video.videoHeight || 480\n }\n btn.disabled = false\n btn.label = t('g.capture')\n })\n }\n})\n"],"names":["ClipspaceDialog","ComfyDialog","__name","name","contextPredicate","callback","item","$el","ComfyApp","img_preview","self","children","buttons","idx","combo_items","imgs","i","combo1","event","row1","combo2","row2","td","row3","app","ext","ctxMenu","LiteGraph","values","options","ctx","filter","items","displayedItems","itemCount","clickedComboValue","LGraphCanvas","w","isComboWidget","v","selectedIndex","selectedItem","updateSelected","positionList","scale","shift","term","isVisible","d","top","bodyRect","rootRect","applyToGraph","extraLinks","links","l","linkInfo","node","input","widgetName","widget","onNodeCreated","useChainCallback","comboWidget","shallowReactive","updateCombo","addOption","newCount","value","lastWidget","nodeType","nodeData","useExtensionService","widgets","workflowNode","widgetIndex","prompt","processDynamicPrompt","editAttentionDelta","incrementWeight","weight","delta","floatWeight","newWeight","findNearestEnclosure","text","cursorPos","start","end","openCount","closeCount","addWeightToParentheses","parenRegex","parenMatch","floatRegex","floatMatch","editAttention","inputField","selectedText","nearestEnclosure","delimiters","weightDelta","updatedText","_","PYTHON_MIRROR","checkMirrorReachable","mirror","isValidUrl","electronAPI","isElectron","getElectronAPI","desktopAppVersion","workflowStore","useWorkflowStore","toastStore","useToastStore","staticUrls","buildDocsUrl","useExternalLink","onChangeRestartApp","newValue","oldValue","updateInfo","t","useDialogService","error","log","ExecutableGroupNodeChildDTO","ExecutableNodeDTO","subgraphNodePath","nodesByExecutionId","subgraphNode","groupNodeHandler","slot","inputNode","link","inputNodeId","inputNodeDto","id","ORDER","merge","target","source","key","sv","tv","ManageGroupDialog","tab","index","force","PREFIX","SEPARATOR","GroupNodeHandler","group","reset","nodes","n","ordered","DraggableList","oldPosition","newPosition","props","nodeIndex","section","prop","groupMod","nodesMod","nodeMod","typeMod","objMod","placeholder","checked","checkable","mods","e","config","oldName","inputs","innerNodeDef","outputs","groupOutputs","type","groupOutputIndex","visible","groupNodes","a","b","pages","p","page","outer","g","nodesByType","recreateNodes","types","nodeMods","keys","orderedNodes","orderedMods","orderedConfig","order","GroupNodeConfig","IGNORE_KEYS","getRange","min","max","mergeNumericInputSpec","spec1","spec2","options1","options2","range1","range2","step1","step2","mergedOptions","lcm","mergeCommonInputSpec","mergeComboInputSpec","comboOptions1","getComboSpecComboOptions","comboOptions2","intersection","getInputSpecType","value1","value2","mergeInputSpec","type1","type2","isIntInputSpec","isFloatInputSpec","isComboInputSpec","isPrimitiveNode","replacePropertyName","PrimitiveNode","LGraphNode","title","applyTextReplacements","GET_CONFIG","#onFirstConnection","#mergeWidgetConfig","_type","_index","connected","target_node","target_slot","ComfyWidgets","valid","#isValidConnection","recreating","linkId","theirNode","getWidgetType","#createWidget","CONFIG","inputData","oldWidth","oldHeight","isValidWidgetType","theirWidget","control_value","addValueControlWidgets","controlValues","sz","#removeWidgets","output","hasConfig","config1","theirInput","forceUpdate","config2","mergeIfValid","getWidgetConfig","getConfig","convertToInput","setWidgetConfig","NodeSlot","graph","originNode","recreateWidget","customSpec","_nodeData","origOnInputDblClick","args","pos","Workflow","data","extra","GroupNodeBuilder","nodesInOrder","storeLinkTypes","storeExternalLinks","hasExternal","serialised","serialise","GROUP","seenInputs","seenOutputs","#convertedToProcess","useNodeDefStore","sourceNodeId","sourceNodeSlot","targetNodeId","targetNodeSlot","def","globalDefs","linksFrom","fromTypeName","fromType","linksTo","rerouteType","targetDef","targetWidget","inputName","customConfig","inp","prefix","inputNames","slots","converted","widgetMap","useWidgetStore","convertedIndex","__","primitiveDef","primitiveConfig","toPrimitive","toWidget","inputMap","convertedSlots","k","inputMapping","oldToNew","outputId","hasLink","label","o","missingNodeTypes","groupData","hasMissing","innerNodes","innerNodeIndex","innerNode","externalSlot","innerLink","computedNodeDtos","visited","subgraphInstanceIdPath","currentId","aVeryRealNode","groupNode","addInnerNodes","c","ids","deserialiseAndCreate","x","y","left","selectedIds","newNodes","newNode","map","newName","outerWidget","newWidget","reconnectInputs","innerInputId","groupSlotId","reconnectOutputs","groupOutputId","targetNode","getExtraMenuOptions","optionIndex","manageGroupNodes","onDrawTitleBox","height","fill","onDrawForeground","progressState","useExecutionStore","message","onExecutionStart","handleEvent","getId","getEvent","handler","detail","api","executing","executed","onRemoved","defs","old","newWidgetName","primitiveLinked","linked","rerouteLinks","targetSlot","_node","nodeId","primitiveId","targetWidgetName","targetWidgetIndex","primitiveNode","len","offset","linkedShift","mainWidget","innerWidget","originalNode","newSlot","originSlot","targetId","actualOriginId","builder","res","replaceLegacySeparators","convertSelectedNodesToGroupNode","SubgraphNode","convertDisabled","selected","ungroupSelectedGroupNodes","canvas","convertEnabled","groups","manageDisabled","graphData","setNodeMode","mode","addNodesToGroup","padding","useSettingStore","LGraphGroup","nodesInGroup","allNodesAreSameMode","onExecuted","aImages","bImages","rand","beforeUrl","afterUrl","EXPORT_FORMATS","createExportMenuItems","load3d","_value","_options","prev_menu","submenuOptions","format","Load3DConfiguration","properties","loadFolder","filePath","setting","width","onModelWidgetUpdate","modelWidget","cameraState","originalCallback","currentValue","bgImagePath","sceneConfig","cameraConfig","lightConfig","isFirstLoad","filename","modelUrl","Load3dUtils","modelConfig","pathParts","part","subfolder","inputSpecLoad3D","inputSpecPreview3D","handleModelUpload","files","resourceFolder","uploadPath","useLoad3d","handleResourcesUpload","createFileInput","accept","multiple","selectedNodes","selectedNode","isLoad3dNode","useDialogStore","Load3DViewerContent","useLoad3dService","fileInput","resourcesInput","ComponentWidgetImpl","Load3D","addWidget","nextTick","sceneWidget","settings","currentLoad3d","nodeToLoad3dMap","imageData","maskData","normalData","dataMask","dataNormal","returnVal","recordingData","recording","_nodeType","lastTimeModelFile","msg","openMaskEditor","useMaskEditor","openMaskEditorFromClipspace","isOpened","changeBrushSize","sizeChanger","store","useMaskEditorStore","oldBrushSize","newBrushSize","file","ManageTemplates","btns","templates","reader","importFile","template","json","blob","downloadBlob","nameInput","el","prev_i","rect","row","that","manage","clipboardAction","cb","_canvas","nodeIds","subItems","NoteNode","MarkdownNoteNode","showValueWidget","showValueWidgetPlain","showAsPlaintextWidget","previewWidgets","previewWidget","RerouteNode","cloned","linksToDisconnect","currentNode","updateNodes","inputType","outputType","nodeInput","nodeOutType","keep","displayType","color","widgetConfig","widgetType","targetInput","merged","saveNodeTypes","r","inputSpec","fileInfo","drawSelectionBorder","selectedItems","bounds","createBounds","borderWidth","dashSize","originalDrawForeground","visibleArea","touchZooming","touchCount","touchDist","touchTime","lastTouch","lastScale","getMultiTouchPos","getMultiTouchCenter","touch","resetTouchState","onlyTouch","deltaX","deltaY","newTouchDist","center","newX","newY","oldScale","newScale","convertScaleToOffset","oldCenter","newCenter","processMouseDown","processMouseMove","newVal","inputKey","customProperties","lowerType","maxNum","uploadFile","audioWidget","audioUIWidget","updateNode","pasted","body","resp","path","getResourceURL","splitFilePath","audio","audios","nodeOutputs","nodeLocatorId","getNodeByLocatorId","onAudioWidgetUpdate","onGraphConfigured","handleUpload","isAudioFile","openFileSelection","useNodeFileInput","uploadWidget","useNodeDragAndDrop","useNodePaste","mediaRecorder","isRecording","audioChunks","currentStream","recordWidget","stopPromise","stopResolve","resolve","audioSrc","useAudioService","ExtendableMediaRecorder","audioBlob","err","originalOnRemoved","isMediaUploadComboInput","inputOptions","isComboInputSpecV1","createUploadInput","imageInputName","imageInputOptions","required","found","WEBCAM_READY","container","video","stream","camera","h","captureOnQueue","capture","img","btn"],"mappings":"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"}