merge main into rh-test

This commit is contained in:
bymyself
2025-09-28 15:33:29 -07:00
parent 1c0f151d02
commit ff0c15b119
1317 changed files with 85439 additions and 18373 deletions

View File

@@ -1,7 +1,4 @@
import type {
BaseSearchParamsWithoutQuery,
Hit
} from 'algoliasearch/dist/lite/browser'
import type { BaseSearchParamsWithoutQuery } from 'algoliasearch/dist/lite/browser'
import type { components } from '@/types/comfyRegistryTypes'
@@ -13,15 +10,6 @@ type SafeNestedProperty<
type RegistryNodePack = components['schemas']['Node']
/**
* Result of searching the Algolia index.
* Represents the entire result of a search query.
*/
export type SearchPacksResult = {
nodePacks: Hit<AlgoliaNodePack>[]
querySuggestions: Hit<NodesIndexSuggestion>[]
}
/**
* Node pack record after it has been mapped to Algolia index format.
* @see https://github.com/Comfy-Org/comfy-api/blob/main/mapper/algolia.go

View File

@@ -1,5 +1,8 @@
declare module 'algoliasearch/dist/lite/builds/browser' {
import { LiteClient, ClientOptions } from 'algoliasearch/dist/lite/browser'
import type {
LiteClient,
ClientOptions
} from 'algoliasearch/dist/lite/browser'
/**
* Creates a new Algolia Search client that uses the Lite API Client (Browser version)

View File

@@ -1,12 +1,18 @@
import type { HTMLAttributes } from 'vue'
export type ButtonSize = 'fit-content' | 'sm' | 'md'
type ButtonType = 'primary' | 'secondary' | 'transparent'
type ButtonBorder = boolean
export interface BaseButtonProps {
size?: 'fit-content' | 'sm' | 'md'
type?: 'primary' | 'secondary' | 'transparent'
size?: ButtonSize
type?: ButtonType
border?: ButtonBorder
disabled?: boolean
class?: HTMLAttributes['class']
}
export const getButtonSizeClasses = (size: BaseButtonProps['size'] = 'md') => {
export const getButtonSizeClasses = (size: ButtonSize = 'md') => {
const sizeClasses = {
'fit-content': '',
sm: 'px-2 py-1.5 text-xs',
@@ -15,30 +21,51 @@ export const getButtonSizeClasses = (size: BaseButtonProps['size'] = 'md') => {
return sizeClasses[size]
}
export const getButtonTypeClasses = (
type: BaseButtonProps['type'] = 'primary'
) => {
const typeClasses = {
export const getButtonTypeClasses = (type: ButtonType = 'primary') => {
const baseByType = {
primary:
'bg-neutral-900 border-none text-white dark-theme:bg-white dark-theme:text-neutral-900',
secondary:
'bg-white border-none text-neutral-950 dark-theme:bg-zinc-700 dark-theme:text-white',
transparent:
'bg-transparent border-none text-neutral-600 dark-theme:text-neutral-400'
} as const
return baseByType[type]
}
export const getBorderButtonTypeClasses = (type: ButtonType = 'primary') => {
const baseByType = {
primary:
'bg-neutral-900 text-white dark-theme:bg-white dark-theme:text-neutral-900',
secondary:
'bg-white text-neutral-950 dark-theme:bg-zinc-700 dark-theme:text-white',
transparent: 'bg-transparent text-neutral-600 dark-theme:text-neutral-400'
}
return typeClasses[type]
} as const
const borderByType = {
primary: 'border border-solid border-white dark-theme:border-neutral-900',
secondary: 'border border-solid border-neutral-950 dark-theme:border-white',
transparent:
'border border-solid border-neutral-950 dark-theme:border-white'
} as const
return `${baseByType[type]} ${borderByType[type]}`
}
export const getIconButtonSizeClasses = (
size: BaseButtonProps['size'] = 'md'
) => {
export const getIconButtonSizeClasses = (size: ButtonSize = 'md') => {
const sizeClasses = {
'fit-content': 'w-auto h-auto',
sm: 'w-6 h-6 text-xs !rounded-md',
md: 'w-8 h-8 text-sm'
sm: 'size-8 text-xs !rounded-md',
md: 'size-10 text-sm'
}
return sizeClasses[size]
}
export const getBaseButtonClasses = () => {
return 'flex items-center justify-center flex-shrink-0 outline-none border-none rounded-lg cursor-pointer transition-all duration-200'
return [
'flex items-center justify-center shrink-0',
'outline-hidden rounded-lg cursor-pointer transition-all duration-200',
'disabled:opacity-50 disabled:pointer-events-none'
].join(' ')
}

View File

@@ -1,6 +1,7 @@
import { Positionable } from '@/lib/litegraph/src/interfaces'
import type { Positionable } from '@/lib/litegraph/src/interfaces'
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
import type { ComfyWorkflowJSON } from '@/schemas/comfyWorkflowSchema'
import type { SettingParams } from '@/platform/settings/types'
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { Keybinding } from '@/schemas/keyBindingSchema'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import type { ComfyApp } from '@/scripts/app'
@@ -8,9 +9,8 @@ import type { ComfyWidgetConstructor } from '@/scripts/widgets'
import type { ComfyCommand } from '@/stores/commandStore'
import type { AuthUserInfo } from '@/types/authTypes'
import type { BottomPanelExtension } from '@/types/extensionTypes'
import type { SettingParams } from '@/types/settingTypes'
export type Widgets = Record<string, ComfyWidgetConstructor>
type Widgets = Record<string, ComfyWidgetConstructor>
export interface AboutPageBadge {
label: string
@@ -18,7 +18,7 @@ export interface AboutPageBadge {
icon: string
}
export type MenuCommandGroup = {
type MenuCommandGroup = {
/**
* The path to the menu group.
*/
@@ -168,8 +168,9 @@ export interface ComfyExtension {
): Promise<void> | void
/**
* Fired whenever authentication resolves, providing the user id.
* Fired whenever authentication resolves, providing the anonymized user id..
* Extensions can register at any time and will receive the latest value immediately.
* This is an experimental API and may be changed or removed in the future.
*/
onAuthUserResolved?(user: AuthUserInfo, app: ComfyApp): Promise<void> | void

View File

@@ -1,244 +0,0 @@
import type { InjectionKey, Ref } from 'vue'
import type { ComfyWorkflowJSON } from '@/schemas/comfyWorkflowSchema'
import type { AlgoliaNodePack } from '@/types/algoliaTypes'
import type { components } from '@/types/comfyRegistryTypes'
import type { SearchMode } from '@/types/searchServiceTypes'
type WorkflowNodeProperties = ComfyWorkflowJSON['nodes'][0]['properties']
export type RegistryPack = components['schemas']['Node']
export type MergedNodePack = RegistryPack & AlgoliaNodePack
export const isMergedNodePack = (
nodePack: RegistryPack | AlgoliaNodePack
): nodePack is MergedNodePack => 'comfy_nodes' in nodePack
export type PackField = keyof RegistryPack | null
export const IsInstallingKey: InjectionKey<Ref<boolean>> =
Symbol('isInstalling')
export enum ManagerWsQueueStatus {
DONE = 'done',
IN_PROGRESS = 'in_progress'
}
export enum ManagerTab {
All = 'all',
Installed = 'installed',
Workflow = 'workflow',
Missing = 'missing',
UpdateAvailable = 'updateAvailable'
}
export enum SortableAlgoliaField {
Downloads = 'total_install',
Created = 'create_time',
Updated = 'update_time',
Publisher = 'publisher_id',
Name = 'name'
}
export interface TabItem {
id: ManagerTab
label: string
icon: string
}
export interface SearchOption<T> {
id: T
label: string
}
export type TaskLog = {
taskName: string
logs: string[]
}
export interface UseNodePacksOptions {
immediate?: boolean
maxConcurrent?: number
}
enum ManagerPackState {
/** Pack is installed and enabled */
INSTALLED = 'installed',
/** Pack is installed but disabled */
DISABLED = 'disabled',
/** Pack is not installed */
NOT_INSTALLED = 'not_installed',
/** Pack failed to import */
IMPORT_FAILED = 'import_failed',
/** Pack has an update available */
NEEDS_UPDATE = 'needs_update'
}
enum ManagerPackInstallType {
/** Installed via git clone */
GIT = 'git-clone',
/** Installed via file copy */
COPY = 'copy',
/** Installed from the Comfy Registry */
REGISTRY = 'cnr'
}
export enum SelectedVersion {
/** Latest version of the pack from the registry */
LATEST = 'latest',
/** Latest commit of the pack from its GitHub repository */
NIGHTLY = 'nightly'
}
export enum ManagerChannel {
/** All packs except those with instability or security issues */
DEFAULT = 'default',
/** Packs that were recently updated */
RECENT = 'recent',
/** Packs that were superseded by distinct replacements of some type */
LEGACY = 'legacy',
/** Packs that were forked as a result of the original pack going unmaintained */
FORKED = 'forked',
/** Packs with instability or security issues suitable only for developers */
DEV = 'dev',
/** Packs suitable for beginners */
TUTORIAL = 'tutorial'
}
export enum ManagerDatabaseSource {
/** Get pack info from the Comfy Registry */
REMOTE = 'remote',
/** If set to `local`, the channel is ignored */
LOCAL = 'local',
/** Get pack info from the cached response from the Comfy Registry (1 day TTL) */
CACHE = 'cache'
}
export interface ManagerQueueStatus {
/** `done_count` + `in_progress_count` + number of items queued */
total_count: number
/** Task worker thread is alive, a queued operation is running */
is_processing: boolean
/** Number of items in the queue that have been completed */
done_count: number
/** Number of items in the queue that are currently running */
in_progress_count: number
}
export interface ManagerPackInfo {
/** Either github-author/github-repo or name of pack from the registry (not id) */
id: WorkflowNodeProperties['aux_id'] | WorkflowNodeProperties['cnr_id']
/** Semantic version or Git commit hash */
version: WorkflowNodeProperties['ver']
}
export interface ManagerPackInstalled {
/**
* The version of the pack that is installed.
* Git commit hash or semantic version.
*/
ver: WorkflowNodeProperties['ver']
/**
* The name of the pack if the pack is installed from the registry.
* Corresponds to `Node#name` in comfy-api.
*/
cnr_id: WorkflowNodeProperties['cnr_id']
/**
* The name of the pack if the pack is installed from github.
* In the format author/repo-name. If the pack is installed from the registry, this is `null`.
*/
aux_id: WorkflowNodeProperties['aux_id'] | null
enabled: boolean
}
/**
* Returned by `/customnode/installed`
*/
export type InstalledPacksResponse = Record<
NonNullable<RegistryPack['name']>,
ManagerPackInstalled
>
/**
* Returned by `/customnode/getlist`
*/
export interface ManagerPack extends ManagerPackInfo {
/** Pack author name or 'Unclaimed' if the pack was added automatically via GitHub crawl. */
author: components['schemas']['Node']['author']
/** Files included in the pack */
files: string[]
/** The type of installation that was used to install the pack */
reference: string
/** The display name of the pack */
title: string
/** The latest version of the pack */
cnr_latest: SelectedVersion
/** The github link to the repository of the pack */
repository: string
/** The state of the pack */
state: ManagerPackState
/** The state of the pack update */
'update-state': 'false' | 'true' | null
/** The number of stars the pack has on GitHub. Distinct from registry stars */
stars: number
/**
* The last time the pack was updated. In ISO 8601 format.
* @example '2024-05-22 20:00:00'
*/
last_update: string
health: string
description: string
trust: boolean
install_type: ManagerPackInstallType
}
/**
* Returned by `/customnode/getmappings`.
*/
export type ManagerMappings = Record<
NonNullable<components['schemas']['Node']['name']>,
[
/** List of ComfyNode names included in the pack */
Array<components['schemas']['ComfyNode']['comfy_node_name']>,
{
/** The display name of the pack */
title_aux: string
}
]
>
/**
* Payload for `/manager/queue/install`
*/
export interface InstallPackParams extends ManagerPackInfo {
/**
* Semantic version, Git commit hash, `latest`, or `nightly`.
*/
selected_version: WorkflowNodeProperties['ver'] | SelectedVersion
/**
* The GitHub link to the repository of the pack to install.
* Required if `selected_version` is `nightly`.
*/
repository: string
/**
* List of PyPi dependency names associated with the pack.
* Used in coordination with pip package whitelist and version lock features.
*/
pip?: string[]
mode: ManagerDatabaseSource
channel: ManagerChannel
skip_post_install?: boolean
}
/**
* Params for `/manager/queue/update_all`
*/
export interface UpdateAllPacksParams {
mode?: ManagerDatabaseSource
}
export interface ManagerState {
selectedTabId: ManagerTab
searchQuery: string
searchMode: SearchMode
sortField: string
}

View File

@@ -5142,7 +5142,7 @@ export interface components {
| 'doodle_fill'
| 'doodle_offset_fill'
| 'offset_fill'
| 'outline'
| 'outline-solid'
| 'outline_gradient'
| 'uneven_fill'
| '70s'

View File

@@ -1,9 +1,9 @@
import { Component } from 'vue'
import type { Component } from 'vue'
import type { useDialogService } from '@/services/dialogService'
import type { ComfyCommand } from '@/stores/commandStore'
export interface BaseSidebarTabExtension {
interface BaseSidebarTabExtension {
id: string
title: string
icon?: string | Component
@@ -12,7 +12,7 @@ export interface BaseSidebarTabExtension {
label?: string
}
export interface BaseBottomPanelExtension {
interface BaseBottomPanelExtension {
id: string
title?: string // For extensions that provide static titles
titleKey?: string // For core tabs with i18n keys
@@ -32,16 +32,14 @@ export interface CustomExtension {
destroy?: () => void
}
export type VueSidebarTabExtension = BaseSidebarTabExtension & VueExtension
export type CustomSidebarTabExtension = BaseSidebarTabExtension &
CustomExtension
type VueSidebarTabExtension = BaseSidebarTabExtension & VueExtension
type CustomSidebarTabExtension = BaseSidebarTabExtension & CustomExtension
export type SidebarTabExtension =
| VueSidebarTabExtension
| CustomSidebarTabExtension
export type VueBottomPanelExtension = BaseBottomPanelExtension & VueExtension
export type CustomBottomPanelExtension = BaseBottomPanelExtension &
CustomExtension
type VueBottomPanelExtension = BaseBottomPanelExtension & VueExtension
type CustomBottomPanelExtension = BaseBottomPanelExtension & CustomExtension
export type BottomPanelExtension =
| VueBottomPanelExtension
| CustomBottomPanelExtension

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@ import type {
UserData,
UserDataFullInfo
} from '@/schemas/apiSchema'
import { ComfyApp } from '@/scripts/app'
import type { ComfyApp } from '@/scripts/app'
import type {
BottomPanelExtension,

View File

@@ -1,51 +0,0 @@
export type DefaultField = 'Workflow' | 'Logs' | 'SystemStats' | 'Settings'
export interface ReportField {
/**
* The label of the field, shown next to the checkbox if the field is opt-in.
*/
label: string
/**
* A unique identifier for the field, used internally as the key for this field's value.
*/
value: string
/**
* The data associated with this field, sent as part of the report.
*/
getData: () => unknown
/**
* Indicates whether the field requires explicit opt-in from the user
* before its data is included in the report.
*/
optIn: boolean
}
export interface IssueReportPanelProps {
/**
* The type of error being reported. This is used to categorize the error.
*/
errorType: string
/**
* Which of the default fields to include in the report.
*/
defaultFields?: DefaultField[]
/**
* Additional fields to include in the report.
*/
extraFields?: ReportField[]
/**
* Tags that will be added to the report. Tags are used to further categorize the error.
*/
tags?: Record<string, string>
/**
* The title displayed in the dialog.
*/
title?: string
}

View File

@@ -5,12 +5,11 @@ import type {
ExecutionId
} from '@/lib/litegraph/src/litegraph'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { ComfyNodeDef as ComfyNodeDefV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
import type { ComfyNodeDef as ComfyNodeDefV1 } from '@/schemas/nodeDefSchema'
import type { DOMWidget, DOMWidgetOptions } from '@/scripts/domWidget'
import type { NodeId } from '../schemas/comfyWorkflowSchema'
/** ComfyUI extensions of litegraph */
declare module '@/lib/litegraph/src/types/widgets' {
interface IWidgetOptions {
@@ -83,7 +82,7 @@ declare module '@/lib/litegraph/src/litegraph' {
}
// Add interface augmentations into the class itself
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface BaseWidget extends IBaseWidget {}
interface LGraphNode {

View File

@@ -1,7 +1,7 @@
import type {
ComfyApiWorkflow,
ComfyWorkflowJSON
} from '@/schemas/comfyWorkflowSchema'
} from '@/platform/workflow/validation/schemas/workflowSchema'
/**
* Tag names used in ComfyUI metadata
@@ -66,7 +66,7 @@ export type GltfChunkHeader = {
chunkTypeIdentifier: number
}
export type GltfExtras = {
type GltfExtras = {
workflow?: string | object
prompt?: string | object
[key: string]: any
@@ -112,12 +112,12 @@ export type AvifIinfBox = {
entries: AvifInfeBox[]
}
export type AvifIlocItemExtent = {
type AvifIlocItemExtent = {
extent_offset: number
extent_length: number
}
export type AvifIlocItem = {
type AvifIlocItem = {
item_ID: number
data_reference_index: number
base_offset: number

View File

@@ -1,9 +1,12 @@
export interface NavItemData {
id: string
label: string
icon: string
}
export interface NavGroupData {
title: string
items: NavItemData[]
icon?: string
collapsible?: boolean
}

View File

@@ -11,7 +11,7 @@ import type { ComboInputOptions, InputSpec } from '@/schemas/nodeDefSchema'
* Frontend augmentation for image upload combo inputs.
* This extends ComboInputOptions with properties injected by the uploadImage extension.
*/
export interface ImageUploadComboOptions extends ComboInputOptions {
interface ImageUploadComboOptions extends ComboInputOptions {
/**
* Reference to the associated filename combo widget.
* Injected by uploadImage.ts to link upload buttons with their combo widgets.

View File

@@ -1,4 +1,4 @@
import type { NodeId } from '@/schemas/comfyWorkflowSchema'
import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'
/**
* A globally unique identifier for nodes that maintains consistency across

View File

@@ -1,6 +1,7 @@
export enum NodeSourceType {
Core = 'core',
CustomNodes = 'custom_nodes',
Blueprint = 'blueprint',
Unknown = 'unknown'
}
@@ -36,6 +37,13 @@ export const getNodeSource = (python_module?: string): NodeSource => {
displayText: 'Comfy Core',
badgeText: '🦊'
}
} else if (modules[0] === 'blueprint') {
return {
type: NodeSourceType.Blueprint,
className: 'blueprint',
displayText: 'Blueprint',
badgeText: 'bp'
}
} else if (modules[0] === 'custom_nodes') {
const moduleName = modules[1]
// Custom nodes installed via ComfyNodeRegistry will be in the format of

View File

@@ -1,9 +1,3 @@
export enum LinkReleaseTriggerMode {
ALWAYS = 'always',
HOLD_SHIFT = 'hold shift',
NOT_HOLD_SHIFT = 'NOT hold shift'
}
export enum LinkReleaseTriggerAction {
CONTEXT_MENU = 'context menu',
SEARCH_BOX = 'search box',

View File

@@ -20,15 +20,6 @@ export enum HashFunction {
SHA512 = 'sha512'
}
export enum AutoLaunch {
// Let server decide whether to auto launch based on the current environment
Auto = 'auto',
// Disable auto launch
Disable = 'disable',
// Enable auto launch
Enable = 'enable'
}
export enum CudaMalloc {
// Let server decide whether to use CUDA malloc based on the current environment
Auto = 'auto',

View File

@@ -1,69 +0,0 @@
import type { Settings } from '@/schemas/apiSchema'
export type SettingInputType =
| 'boolean'
| 'number'
| 'slider'
| 'knob'
| 'combo'
| 'text'
| 'image'
| 'color'
| 'url'
| 'hidden'
| 'backgroundImage'
export type SettingCustomRenderer = (
name: string,
setter: (v: any) => void,
value: any,
attrs: any
) => HTMLElement
export interface SettingOption {
text: string
value?: any
}
export interface Setting {
id: keyof Settings
onChange?: (value: any, oldValue?: any) => void
name: string
render: () => HTMLElement
}
export interface SettingParams<TValue = unknown> extends FormItem {
id: keyof Settings
defaultValue: any | (() => any)
defaultsByInstallVersion?: Record<`${number}.${number}.${number}`, TValue>
onChange?: (newValue: any, oldValue?: any) => void
// By default category is id.split('.'). However, changing id to assign
// new category has poor backward compatibility. Use this field to overwrite
// default category from id.
// Note: Like id, category value need to be unique.
category?: string[]
experimental?: boolean
deprecated?: boolean
// Deprecated values are mapped to new values.
migrateDeprecatedValue?: (value: any) => any
// Version of the setting when it was added
versionAdded?: string
// Version of the setting when it was last modified
versionModified?: string
}
/**
* The base form item for rendering in a form.
*/
export interface FormItem {
name: string
type: SettingInputType | SettingCustomRenderer
tooltip?: string
attrs?: Record<string, any>
options?: Array<string | SettingOption>
}
export interface ISettingGroup {
label: string
settings: SettingParams[]
}

View File

@@ -0,0 +1,48 @@
/**
* Simplified widget interface for Vue-based node rendering
* Removes all DOM manipulation and positioning concerns
*/
import type { InputSpec as InputSpecV2 } from '@/schemas/nodeDef/nodeDefSchemaV2'
/** Valid types for widget values */
export type WidgetValue =
| string
| number
| boolean
| object
| undefined
| null
| void
| File[]
export interface SimplifiedWidget<
T extends WidgetValue = WidgetValue,
O = Record<string, any>
> {
/** Display name of the widget */
name: string
/** Widget type identifier (e.g., 'STRING', 'INT', 'COMBO') */
type: string
/** Current value of the widget */
value: T
/** Localized display label (falls back to name if not provided) */
label?: string
/** Widget options including filtered PrimeVue props */
options?: O
/** Callback fired when value changes */
callback?: (value: T) => void
/** Optional input specification backing this widget */
spec?: InputSpecV2
/** Optional serialization method for custom value handling */
serializeValue?: () => any
/** Optional method to compute widget size requirements */
computeSize?: () => { minHeight: number; maxHeight?: number }
}

23
src/types/spatialIndex.ts Normal file
View File

@@ -0,0 +1,23 @@
/**
* Type definitions for spatial indexing system
*/
import type { Bounds } from '@/renderer/core/spatial/QuadTree'
/**
* Debug information for a single QuadTree node
*/
export interface QuadNodeDebugInfo {
bounds: Bounds
depth: number
itemCount: number
divided: boolean
children?: QuadNodeDebugInfo[]
}
/**
* Debug information for the entire spatial index
*/
export interface SpatialIndexDebugInfo {
size: number
tree: QuadNodeDebugInfo
}

View File

@@ -1,3 +1,5 @@
import { InjectionKey } from 'vue'
import type { InjectionKey } from 'vue'
export type AssetKind = 'image' | 'video' | 'audio' | 'model' | 'unknown'
export const OnCloseKey: InjectionKey<() => void> = Symbol()

View File

@@ -1,27 +0,0 @@
export interface TemplateInfo {
name: string
/**
* Optional title which is used as the fallback if the name is not in the locales dictionary.
*/
title?: string
tutorialUrl?: string
mediaType: string
mediaSubtype: string
thumbnailVariant?: string
description: string
localizedTitle?: string
localizedDescription?: string
sourceModule?: string
}
export interface WorkflowTemplates {
moduleName: string
templates: TemplateInfo[]
title: string
}
export interface TemplateGroup {
label: string
icon?: string
modules: WorkflowTemplates[]
}