From 164a4c4c25fe275e9cf516bba775a03b32c75967 Mon Sep 17 00:00:00 2001 From: Comfy Org PR Bot Date: Wed, 25 Jun 2025 05:57:41 +0800 Subject: [PATCH 01/31] [chore] Update Comfy Registry API types from comfy-api@af72ba5 (#4264) Co-authored-by: bmcomfy <214909599+bmcomfy@users.noreply.github.com> --- src/types/comfyRegistryTypes.ts | 293 +++++++++++++++++++++++++++++--- 1 file changed, 270 insertions(+), 23 deletions(-) diff --git a/src/types/comfyRegistryTypes.ts b/src/types/comfyRegistryTypes.ts index f96855bf4..e071f2bb0 100644 --- a/src/types/comfyRegistryTypes.ts +++ b/src/types/comfyRegistryTypes.ts @@ -8742,16 +8742,42 @@ export interface components { MoonvalleyUploadResponse: { access_url?: string } + /** @description GitHub release webhook payload based on official webhook documentation */ GithubReleaseWebhook: { - /** @description The action performed on the release */ - action: string + /** + * @description The action performed on the release + * @enum {string} + */ + action: + | 'published' + | 'unpublished' + | 'created' + | 'edited' + | 'deleted' + | 'prereleased' + | 'released' + /** @description The release object */ release: { + /** @description The ID of the release */ + id: number + /** @description The node ID of the release */ + node_id: string + /** @description The API URL of the release */ + url: string + /** @description The HTML URL of the release */ + html_url: string + /** @description The URL to the release assets */ + assets_url?: string + /** @description The URL to upload release assets */ + upload_url?: string /** @description The tag name of the release */ tag_name: string + /** @description The branch or commit the release was created from */ + target_commitish: string /** @description The name of the release */ - name: string + name?: string | null /** @description The release notes/body */ - body: string + body?: string | null /** @description Whether the release is a draft */ draft: boolean /** @description Whether the release is a prerelease */ @@ -8760,33 +8786,228 @@ export interface components { * Format: date-time * @description When the release was created */ - created_at?: string + created_at: string /** * Format: date-time * @description When the release was published */ - published_at?: string + published_at?: string | null + author: components['schemas']['GithubUser'] /** @description URL to the tarball */ - tarball_url?: string + tarball_url: string /** @description URL to the zipball */ - zipball_url?: string - /** @description The branch or commit the release was created from */ - target_commitish: string - } - repository: { - /** @description The name of the repository */ - name: string - /** @description The full name of the repository (owner/repo) */ - full_name: string - /** @description The HTML URL of the repository */ - html_url: string - /** @description The clone URL of the repository */ - clone_url: string + zipball_url: string + /** @description Array of release assets */ + assets: components['schemas']['GithubReleaseAsset'][] } + repository: components['schemas']['GithubRepository'] + sender: components['schemas']['GithubUser'] + organization?: components['schemas']['GithubOrganization'] + installation?: components['schemas']['GithubInstallation'] + enterprise?: components['schemas']['GithubEnterprise'] + } + /** @description A GitHub user */ + GithubUser: { + /** @description The user's login name */ + login: string + /** @description The user's ID */ + id: number + /** @description The user's node ID */ + node_id: string + /** @description URL to the user's avatar */ + avatar_url: string + /** @description The user's gravatar ID */ + gravatar_id?: string | null + /** @description The API URL of the user */ + url: string + /** @description The HTML URL of the user */ + html_url: string + /** + * @description The type of user + * @enum {string} + */ + type: 'Bot' | 'User' | 'Organization' + /** @description Whether the user is a site admin */ + site_admin: boolean + } + /** @description A GitHub repository */ + GithubRepository: { + /** @description The repository ID */ + id: number + /** @description The repository node ID */ + node_id: string + /** @description The name of the repository */ + name: string + /** @description The full name of the repository (owner/repo) */ + full_name: string + /** @description Whether the repository is private */ + private: boolean + owner: components['schemas']['GithubUser'] + /** @description The HTML URL of the repository */ + html_url: string + /** @description The repository description */ + description?: string | null + /** @description Whether the repository is a fork */ + fork: boolean + /** @description The API URL of the repository */ + url: string + /** @description The clone URL of the repository */ + clone_url: string + /** @description The git URL of the repository */ + git_url: string + /** @description The SSH URL of the repository */ + ssh_url: string + /** @description The default branch of the repository */ + default_branch: string + /** + * Format: date-time + * @description When the repository was created + */ + created_at: string + /** + * Format: date-time + * @description When the repository was last updated + */ + updated_at: string + /** + * Format: date-time + * @description When the repository was last pushed to + */ + pushed_at: string + } + /** @description A GitHub release asset */ + GithubReleaseAsset: { + /** @description The asset ID */ + id: number + /** @description The asset node ID */ + node_id: string + /** @description The name of the asset */ + name: string + /** @description The label of the asset */ + label?: string | null + /** @description The content type of the asset */ + content_type: string + /** + * @description The state of the asset + * @enum {string} + */ + state: 'uploaded' | 'open' + /** @description The size of the asset in bytes */ + size: number + /** @description The number of downloads */ + download_count: number + /** + * Format: date-time + * @description When the asset was created + */ + created_at: string + /** + * Format: date-time + * @description When the asset was last updated + */ + updated_at: string + /** @description The browser download URL */ + browser_download_url: string + uploader: components['schemas']['GithubUser'] + } + /** @description A GitHub organization */ + GithubOrganization: { + /** @description The organization's login name */ + login: string + /** @description The organization ID */ + id: number + /** @description The organization node ID */ + node_id: string + /** @description The API URL of the organization */ + url: string + /** @description The API URL of the organization's repositories */ + repos_url: string + /** @description The API URL of the organization's events */ + events_url: string + /** @description The API URL of the organization's hooks */ + hooks_url: string + /** @description The API URL of the organization's issues */ + issues_url: string + /** @description The API URL of the organization's members */ + members_url: string + /** @description The API URL of the organization's public members */ + public_members_url: string + /** @description URL to the organization's avatar */ + avatar_url: string + /** @description The organization description */ + description?: string | null + } + /** @description A GitHub App installation */ + GithubInstallation: { + /** @description The installation ID */ + id: number + account: components['schemas']['GithubUser'] + /** + * @description Repository selection for the installation + * @enum {string} + */ + repository_selection: 'selected' | 'all' + /** @description The API URL for access tokens */ + access_tokens_url: string + /** @description The API URL for repositories */ + repositories_url: string + /** @description The HTML URL of the installation */ + html_url: string + /** @description The GitHub App ID */ + app_id: number + /** @description The target ID */ + target_id: number + /** @description The target type */ + target_type: string + /** @description The installation permissions */ + permissions: Record + /** @description The events the installation subscribes to */ + events: string[] + /** + * Format: date-time + * @description When the installation was created + */ + created_at: string + /** + * Format: date-time + * @description When the installation was last updated + */ + updated_at: string + /** @description The single file name if applicable */ + single_file_name?: string | null + } + /** @description A GitHub enterprise */ + GithubEnterprise: { + /** @description The enterprise ID */ + id: number + /** @description The enterprise slug */ + slug: string + /** @description The enterprise name */ + name: string + /** @description The enterprise node ID */ + node_id: string + /** @description URL to the enterprise avatar */ + avatar_url: string + /** @description The enterprise description */ + description?: string | null + /** @description The enterprise website URL */ + website_url?: string | null + /** @description The HTML URL of the enterprise */ + html_url: string + /** + * Format: date-time + * @description When the enterprise was created + */ + created_at: string + /** + * Format: date-time + * @description When the enterprise was last updated + */ + updated_at: string } ReleaseNote: { /** @description Unique identifier for the release note */ - id?: number + id: number /** * @description The project this release note belongs to * @enum {string} @@ -8805,7 +9026,7 @@ export interface components { * Format: date-time * @description When the release note was published */ - published_at?: string + published_at: string } } responses: never @@ -11011,6 +11232,8 @@ export interface operations { sort?: string[] /** @description node_id to use as filter */ node_id?: string[] + /** @description Comfy UI version */ + comfyui_version?: string /** @description The platform requesting the nodes */ form_factor?: string } @@ -11584,6 +11807,8 @@ export interface operations { project: 'comfyui' | 'comfyui_frontend' | 'desktop' /** @description The current version to filter release notes */ current_version?: string + /** @description The platform requesting the release notes */ + form_factor?: string } header?: never path?: never @@ -11623,7 +11848,20 @@ export interface operations { processReleaseWebhook: { parameters: { query?: never - header?: never + header: { + /** @description The name of the event that triggered the delivery */ + 'X-GitHub-Event': 'release' + /** @description A globally unique identifier (GUID) to identify the event */ + 'X-GitHub-Delivery': string + /** @description The unique identifier of the webhook */ + 'X-GitHub-Hook-ID': string + /** @description HMAC hex digest of the request body using SHA-256 hash function */ + 'X-Hub-Signature-256'?: string + /** @description The type of resource where the webhook was created */ + 'X-GitHub-Hook-Installation-Target-Type'?: string + /** @description The unique identifier of the resource where the webhook was created */ + 'X-GitHub-Hook-Installation-Target-ID'?: string + } path?: never cookie?: never } @@ -11649,6 +11887,15 @@ export interface operations { 'application/json': components['schemas']['ErrorResponse'] } } + /** @description Validation failed or endpoint has been spammed */ + 422: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponse'] + } + } /** @description Internal server error */ 500: { headers: { From 77d2cae301fce866c234f20b59a19c120ce7e462 Mon Sep 17 00:00:00 2001 From: Comfy Org PR Bot Date: Wed, 25 Jun 2025 08:48:39 +0800 Subject: [PATCH 02/31] 1.23.2 (#4266) Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com> --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d4673705d..c0658aeb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@comfyorg/comfyui-frontend", - "version": "1.23.1", + "version": "1.23.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@comfyorg/comfyui-frontend", - "version": "1.23.1", + "version": "1.23.2", "license": "GPL-3.0-only", "dependencies": { "@alloc/quick-lru": "^5.2.0", diff --git a/package.json b/package.json index ff9c02a0b..15bdcfad4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@comfyorg/comfyui-frontend", "private": true, - "version": "1.23.1", + "version": "1.23.2", "type": "module", "repository": "https://github.com/Comfy-Org/ComfyUI_frontend", "homepage": "https://comfy.org", From e17ca7ce7101b8d003e5dc8d1da2df02352aa37b Mon Sep 17 00:00:00 2001 From: Jin Yi Date: Wed, 25 Jun 2025 19:01:40 +0900 Subject: [PATCH 03/31] fix: node migration TypeError (#4260) --- src/schemas/nodeDef/migration.ts | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/schemas/nodeDef/migration.ts b/src/schemas/nodeDef/migration.ts index 8ce9d39b3..e5aa6d484 100644 --- a/src/schemas/nodeDef/migration.ts +++ b/src/schemas/nodeDef/migration.ts @@ -46,22 +46,26 @@ export function transformNodeDefV1ToV2( const outputs: OutputSpecV2[] = [] if (nodeDefV1.output) { - nodeDefV1.output.forEach((outputType, index) => { - const outputSpec: OutputSpecV2 = { - index, - name: nodeDefV1.output_name?.[index] || `output_${index}`, - type: Array.isArray(outputType) ? 'COMBO' : outputType, - is_list: nodeDefV1.output_is_list?.[index] || false, - tooltip: nodeDefV1.output_tooltips?.[index] - } + if (Array.isArray(nodeDefV1.output)) { + nodeDefV1.output.forEach((outputType, index) => { + const outputSpec: OutputSpecV2 = { + index, + name: nodeDefV1.output_name?.[index] || `output_${index}`, + type: Array.isArray(outputType) ? 'COMBO' : outputType, + is_list: nodeDefV1.output_is_list?.[index] || false, + tooltip: nodeDefV1.output_tooltips?.[index] + } - // Add options for combo outputs - if (Array.isArray(outputType)) { - outputSpec.options = outputType - } + // Add options for combo outputs + if (Array.isArray(outputType)) { + outputSpec.options = outputType + } - outputs.push(outputSpec) - }) + outputs.push(outputSpec) + }) + } else { + console.warn('nodeDefV1.output is not an array:', nodeDefV1.output) + } } // Create the V2 node definition From 63181a1ddd1b1307ce6c30f7de6825e86e4fa60f Mon Sep 17 00:00:00 2001 From: Jin Yi Date: Thu, 26 Jun 2025 04:34:19 +0900 Subject: [PATCH 04/31] [Manager] Standardize Card Aspect Ratios & Enhance UI (#4271) Co-authored-by: Claude --- .../content/manager/PackVersionBadge.test.ts | 35 +++--- .../content/manager/PackVersionBadge.vue | 39 +++--- .../manager/button/PackActionButton.vue | 4 +- .../content/manager/packBanner/PackBanner.vue | 16 +-- .../content/manager/packCard/PackCard.vue | 111 ++++++++---------- .../manager/packCard/PackCardFooter.vue | 2 +- 6 files changed, 97 insertions(+), 110 deletions(-) diff --git a/src/components/dialog/content/manager/PackVersionBadge.test.ts b/src/components/dialog/content/manager/PackVersionBadge.test.ts index 10b0381e2..9bd897986 100644 --- a/src/components/dialog/content/manager/PackVersionBadge.test.ts +++ b/src/components/dialog/content/manager/PackVersionBadge.test.ts @@ -1,6 +1,5 @@ import { VueWrapper, mount } from '@vue/test-utils' import { createPinia } from 'pinia' -import Button from 'primevue/button' import PrimeVue from 'primevue/config' import { beforeEach, describe, expect, it, vi } from 'vitest' import { nextTick } from 'vue' @@ -33,6 +32,12 @@ vi.mock('@/stores/comfyManagerStore', () => ({ })) })) +vi.mock('@/composables/nodePack/usePackUpdateStatus', () => ({ + usePackUpdateStatus: vi.fn(() => ({ + isUpdateAvailable: false + })) +})) + const mockToggle = vi.fn() const mockHide = vi.fn() const PopoverStub = { @@ -78,9 +83,9 @@ describe('PackVersionBadge', () => { it('renders with installed version from store', () => { const wrapper = mountComponent() - const button = wrapper.findComponent(Button) - expect(button.exists()).toBe(true) - expect(button.props('label')).toBe('1.5.0') // From mockInstalledPacks + const badge = wrapper.find('[role="button"]') + expect(badge.exists()).toBe(true) + expect(badge.find('span').text()).toBe('1.5.0') // From mockInstalledPacks }) it('falls back to latest_version when not installed', () => { @@ -97,9 +102,9 @@ describe('PackVersionBadge', () => { props: { nodePack: uninstalledPack } }) - const button = wrapper.findComponent(Button) - expect(button.exists()).toBe(true) - expect(button.props('label')).toBe('3.0.0') // From latest_version + const badge = wrapper.find('[role="button"]') + expect(badge.exists()).toBe(true) + expect(badge.find('span').text()).toBe('3.0.0') // From latest_version }) it('falls back to NIGHTLY when no latest_version and not installed', () => { @@ -113,9 +118,9 @@ describe('PackVersionBadge', () => { props: { nodePack: noVersionPack } }) - const button = wrapper.findComponent(Button) - expect(button.exists()).toBe(true) - expect(button.props('label')).toBe(SelectedVersion.NIGHTLY) + const badge = wrapper.find('[role="button"]') + expect(badge.exists()).toBe(true) + expect(badge.find('span').text()).toBe(SelectedVersion.NIGHTLY) }) it('falls back to NIGHTLY when nodePack.id is missing', () => { @@ -127,16 +132,16 @@ describe('PackVersionBadge', () => { props: { nodePack: invalidPack } }) - const button = wrapper.findComponent(Button) - expect(button.exists()).toBe(true) - expect(button.props('label')).toBe(SelectedVersion.NIGHTLY) + const badge = wrapper.find('[role="button"]') + expect(badge.exists()).toBe(true) + expect(badge.find('span').text()).toBe(SelectedVersion.NIGHTLY) }) it('toggles the popover when button is clicked', async () => { const wrapper = mountComponent() - // Click the button - await wrapper.findComponent(Button).trigger('click') + // Click the badge + await wrapper.find('[role="button"]').trigger('click') // Verify that the toggle method was called expect(mockToggle).toHaveBeenCalled() diff --git a/src/components/dialog/content/manager/PackVersionBadge.vue b/src/components/dialog/content/manager/PackVersionBadge.vue index a3a366535..5a6ee32e2 100644 --- a/src/components/dialog/content/manager/PackVersionBadge.vue +++ b/src/components/dialog/content/manager/PackVersionBadge.vue @@ -1,18 +1,23 @@ @@ -110,12 +90,11 @@ import ProgressSpinner from 'primevue/progressspinner' import { computed, provide, ref } from 'vue' import { useI18n } from 'vue-i18n' -import ContentDivider from '@/components/common/ContentDivider.vue' import PackVersionBadge from '@/components/dialog/content/manager/PackVersionBadge.vue' import PackBanner from '@/components/dialog/content/manager/packBanner/PackBanner.vue' import PackCardFooter from '@/components/dialog/content/manager/packCard/PackCardFooter.vue' -import { usePackUpdateStatus } from '@/composables/nodePack/usePackUpdateStatus' import { useComfyManagerStore } from '@/stores/comfyManagerStore' +import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import { IsInstallingKey, type MergedNodePack, @@ -130,11 +109,15 @@ const { nodePack, isSelected = false } = defineProps<{ const { d } = useI18n() +const colorPaletteStore = useColorPaletteStore() +const isLightTheme = computed( + () => colorPaletteStore.completedActivePalette.light_theme +) + const isInstalling = ref(false) provide(IsInstallingKey, isInstalling) const { isPackInstalled, isPackEnabled } = useComfyManagerStore() -const { isUpdateAvailable } = usePackUpdateStatus(nodePack) const isInstalled = computed(() => isPackInstalled(nodePack?.id)) const isDisabled = computed( @@ -167,14 +150,14 @@ const formattedLatestVersionDate = computed(() => { position: relative; } -.selected-card::before { +.selected-card::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; - border: 3px solid var(--p-primary-color); + border: 4px solid var(--p-primary-color); border-radius: 0.5rem; pointer-events: none; z-index: 100; diff --git a/src/components/dialog/content/manager/packCard/PackCardFooter.vue b/src/components/dialog/content/manager/packCard/PackCardFooter.vue index 659393c14..1062f2cac 100644 --- a/src/components/dialog/content/manager/packCard/PackCardFooter.vue +++ b/src/components/dialog/content/manager/packCard/PackCardFooter.vue @@ -1,6 +1,6 @@ - diff --git a/src/components/graph/SelectionToolbox.vue b/src/components/graph/SelectionToolbox.vue index 5caa3bee7..3b316b06b 100644 --- a/src/components/graph/SelectionToolbox.vue +++ b/src/components/graph/SelectionToolbox.vue @@ -12,6 +12,7 @@ + +