mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-08 08:08:04 +00:00
Compare commits
1 Commits
codex/cove
...
matt/be-22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c46eefcc43 |
@@ -14,6 +14,7 @@ import { useComfyManagerService } from '@/workbench/extensions/manager/services/
|
||||
import { useComfyManagerStore } from '@/workbench/extensions/manager/stores/comfyManagerStore'
|
||||
import { useConflictDetectionStore } from '@/workbench/extensions/manager/stores/conflictDetectionStore'
|
||||
import type { ConflictDetectionResult } from '@/workbench/extensions/manager/types/conflictDetectionTypes'
|
||||
import type * as ConflictUtils from '@/workbench/extensions/manager/utils/conflictUtils'
|
||||
import { checkVersionCompatibility } from '@/workbench/extensions/manager/utils/versionUtil'
|
||||
|
||||
// Mock @vueuse/core until function
|
||||
@@ -51,41 +52,15 @@ vi.mock('@/workbench/extensions/manager/utils/systemCompatibility', () => ({
|
||||
normalizeOSList: vi.fn((list) => list)
|
||||
}))
|
||||
|
||||
vi.mock('@/workbench/extensions/manager/utils/conflictUtils', () => ({
|
||||
consolidateConflictsByPackage: vi.fn((results) => results),
|
||||
createBannedConflict: vi.fn((isBanned) =>
|
||||
isBanned
|
||||
? {
|
||||
type: 'banned',
|
||||
current_value: 'installed',
|
||||
required_value: 'not_banned'
|
||||
}
|
||||
: null
|
||||
),
|
||||
createPendingConflict: vi.fn((isPending) =>
|
||||
isPending
|
||||
? {
|
||||
type: 'pending',
|
||||
current_value: 'installed',
|
||||
required_value: 'not_pending'
|
||||
}
|
||||
: null
|
||||
),
|
||||
generateConflictSummary: vi.fn((results, duration) => ({
|
||||
total_packages: results.length,
|
||||
compatible_packages: results.filter(
|
||||
(r: ConflictDetectionResult) => r.is_compatible
|
||||
).length,
|
||||
conflicted_packages: results.filter(
|
||||
(r: ConflictDetectionResult) => r.has_conflict
|
||||
).length,
|
||||
banned_packages: 0,
|
||||
pending_packages: 0,
|
||||
conflicts_by_type_details: {},
|
||||
last_check_timestamp: new Date().toISOString(),
|
||||
check_duration_ms: duration
|
||||
}))
|
||||
}))
|
||||
vi.mock('@/workbench/extensions/manager/utils/conflictUtils', async () => {
|
||||
const actual = await vi.importActual<typeof ConflictUtils>(
|
||||
'@/workbench/extensions/manager/utils/conflictUtils'
|
||||
)
|
||||
return {
|
||||
...actual,
|
||||
consolidateConflictsByPackage: vi.fn((results) => results)
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock(
|
||||
'@/workbench/extensions/manager/composables/useConflictAcknowledgment',
|
||||
@@ -448,6 +423,37 @@ describe('useConflictDetection', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('checkNodeCompatibility status derivation', () => {
|
||||
it('flags a banned conflict for a Node with NodeStatusBanned', () => {
|
||||
const { checkNodeCompatibility } = useConflictDetection()
|
||||
const { conflicts } = checkNodeCompatibility({
|
||||
status: 'NodeStatusBanned'
|
||||
} as components['schemas']['Node'])
|
||||
|
||||
expect(conflicts.map((c) => c.type)).toContain('banned')
|
||||
})
|
||||
|
||||
it('flags a banned conflict for a NodeVersion with NodeVersionStatusBanned', () => {
|
||||
const { checkNodeCompatibility } = useConflictDetection()
|
||||
const { conflicts } = checkNodeCompatibility({
|
||||
status: 'NodeVersionStatusBanned'
|
||||
} as components['schemas']['NodeVersion'])
|
||||
|
||||
expect(conflicts.map((c) => c.type)).toContain('banned')
|
||||
})
|
||||
|
||||
it('flags a pending conflict for a NodeVersion with NodeVersionStatusPending', () => {
|
||||
const { checkNodeCompatibility } = useConflictDetection()
|
||||
const { conflicts } = checkNodeCompatibility({
|
||||
status: 'NodeVersionStatusPending'
|
||||
} as components['schemas']['NodeVersion'])
|
||||
|
||||
const types = conflicts.map((c) => c.type)
|
||||
expect(types).toContain('pending')
|
||||
expect(types).not.toContain('banned')
|
||||
})
|
||||
})
|
||||
|
||||
describe('computed properties', () => {
|
||||
it('should expose conflict status from store', () => {
|
||||
mockConflictedPackages = [
|
||||
|
||||
@@ -16,7 +16,6 @@ import type {
|
||||
RegistryOS
|
||||
} from '@/workbench/extensions/manager/types/compatibility.types'
|
||||
import type {
|
||||
ConflictDetail,
|
||||
ConflictDetectionResponse,
|
||||
ConflictDetectionResult,
|
||||
ImportFailureMap,
|
||||
@@ -26,18 +25,10 @@ import type {
|
||||
} from '@/workbench/extensions/manager/types/conflictDetectionTypes'
|
||||
import {
|
||||
consolidateConflictsByPackage,
|
||||
createBannedConflict,
|
||||
createPendingConflict
|
||||
evaluateCompatibility
|
||||
} from '@/workbench/extensions/manager/utils/conflictUtils'
|
||||
import {
|
||||
checkAcceleratorCompatibility,
|
||||
checkOSCompatibility,
|
||||
normalizeOSList
|
||||
} from '@/workbench/extensions/manager/utils/systemCompatibility'
|
||||
import {
|
||||
checkVersionCompatibility,
|
||||
getFrontendVersion
|
||||
} from '@/workbench/extensions/manager/utils/versionUtil'
|
||||
import { normalizeOSList } from '@/workbench/extensions/manager/utils/systemCompatibility'
|
||||
import { getFrontendVersion } from '@/workbench/extensions/manager/utils/versionUtil'
|
||||
|
||||
/**
|
||||
* Composable for conflict detection system.
|
||||
@@ -276,51 +267,21 @@ export function useConflictDetection() {
|
||||
packageReq: NodeRequirements,
|
||||
systemEnvInfo: SystemEnvironment
|
||||
): ConflictDetectionResult {
|
||||
const conflicts: ConflictDetail[] = []
|
||||
|
||||
// 1. ComfyUI version conflict check
|
||||
const versionConflict = checkVersionCompatibility(
|
||||
'comfyui_version',
|
||||
systemEnvInfo.comfyui_version,
|
||||
packageReq.supported_comfyui_version
|
||||
const conflicts = evaluateCompatibility(
|
||||
{
|
||||
supported_os: packageReq.supported_os as RegistryOS[] | undefined,
|
||||
supported_accelerators: packageReq.supported_accelerators as
|
||||
| RegistryAccelerator[]
|
||||
| undefined,
|
||||
supported_comfyui_version: packageReq.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version:
|
||||
packageReq.supported_comfyui_frontend_version,
|
||||
isBanned: packageReq.is_banned,
|
||||
isPending: packageReq.is_pending
|
||||
},
|
||||
systemEnvInfo
|
||||
)
|
||||
if (versionConflict) conflicts.push(versionConflict)
|
||||
|
||||
// 2. Frontend version conflict check
|
||||
const frontendConflict = checkVersionCompatibility(
|
||||
'frontend_version',
|
||||
systemEnvInfo.frontend_version,
|
||||
packageReq.supported_comfyui_frontend_version
|
||||
)
|
||||
if (frontendConflict) conflicts.push(frontendConflict)
|
||||
|
||||
// 3. OS compatibility check
|
||||
const osConflict = checkOSCompatibility(
|
||||
packageReq.supported_os as RegistryOS[] | undefined,
|
||||
systemEnvInfo.os
|
||||
)
|
||||
if (osConflict) conflicts.push(osConflict)
|
||||
|
||||
// 4. Accelerator compatibility check
|
||||
const acceleratorConflict = checkAcceleratorCompatibility(
|
||||
packageReq.supported_accelerators as RegistryAccelerator[] | undefined,
|
||||
systemEnvInfo.accelerator
|
||||
)
|
||||
if (acceleratorConflict) conflicts.push(acceleratorConflict)
|
||||
|
||||
// 5. Banned package check using shared logic
|
||||
const bannedConflict = createBannedConflict(packageReq.is_banned)
|
||||
if (bannedConflict) {
|
||||
conflicts.push(bannedConflict)
|
||||
}
|
||||
|
||||
// 6. Registry data availability check using shared logic
|
||||
const pendingConflict = createPendingConflict(packageReq.is_pending)
|
||||
if (pendingConflict) {
|
||||
conflicts.push(pendingConflict)
|
||||
}
|
||||
|
||||
// Generate result
|
||||
const hasConflict = conflicts.length > 0
|
||||
|
||||
return {
|
||||
@@ -615,63 +576,26 @@ export function useConflictDetection() {
|
||||
function checkNodeCompatibility(
|
||||
node: Node | components['schemas']['NodeVersion']
|
||||
) {
|
||||
const conflicts: ConflictDetail[] = []
|
||||
|
||||
// Check OS compatibility
|
||||
const osConflict = checkOSCompatibility(
|
||||
normalizeOSList(node.supported_os),
|
||||
systemEnvironment.value?.os
|
||||
const conflicts = evaluateCompatibility(
|
||||
{
|
||||
supported_os: normalizeOSList(node.supported_os),
|
||||
supported_accelerators:
|
||||
node.supported_accelerators as RegistryAccelerator[],
|
||||
supported_comfyui_version: node.supported_comfyui_version,
|
||||
supported_comfyui_frontend_version:
|
||||
node.supported_comfyui_frontend_version,
|
||||
isBanned:
|
||||
node.status === 'NodeStatusBanned' ||
|
||||
node.status === 'NodeVersionStatusBanned',
|
||||
isPending: node.status === 'NodeVersionStatusPending'
|
||||
},
|
||||
{
|
||||
comfyui_version: systemEnvironment.value?.comfyui_version,
|
||||
frontend_version: getFrontendVersion(),
|
||||
os: systemEnvironment.value?.os,
|
||||
accelerator: systemEnvironment.value?.accelerator
|
||||
}
|
||||
)
|
||||
if (osConflict) {
|
||||
conflicts.push(osConflict)
|
||||
}
|
||||
|
||||
// Check Accelerator compatibility
|
||||
const acceleratorConflict = checkAcceleratorCompatibility(
|
||||
node.supported_accelerators as RegistryAccelerator[],
|
||||
systemEnvironment.value?.accelerator
|
||||
)
|
||||
if (acceleratorConflict) {
|
||||
conflicts.push(acceleratorConflict)
|
||||
}
|
||||
|
||||
// Check ComfyUI version compatibility
|
||||
const comfyUIVersionConflict = checkVersionCompatibility(
|
||||
'comfyui_version',
|
||||
systemEnvironment.value?.comfyui_version,
|
||||
node.supported_comfyui_version
|
||||
)
|
||||
if (comfyUIVersionConflict) {
|
||||
conflicts.push(comfyUIVersionConflict)
|
||||
}
|
||||
|
||||
// Check ComfyUI Frontend version compatibility
|
||||
const currentFrontendVersion = getFrontendVersion()
|
||||
const frontendVersionConflict = checkVersionCompatibility(
|
||||
'frontend_version',
|
||||
currentFrontendVersion,
|
||||
node.supported_comfyui_frontend_version
|
||||
)
|
||||
if (frontendVersionConflict) {
|
||||
conflicts.push(frontendVersionConflict)
|
||||
}
|
||||
|
||||
// Check banned package status using shared logic
|
||||
const bannedConflict = createBannedConflict(
|
||||
node.status === 'NodeStatusBanned' ||
|
||||
node.status === 'NodeVersionStatusBanned'
|
||||
)
|
||||
if (bannedConflict) {
|
||||
conflicts.push(bannedConflict)
|
||||
}
|
||||
|
||||
// Check pending status using shared logic
|
||||
const pendingConflict = createPendingConflict(
|
||||
node.status === 'NodeVersionStatusPending'
|
||||
)
|
||||
if (pendingConflict) {
|
||||
conflicts.push(pendingConflict)
|
||||
}
|
||||
|
||||
return {
|
||||
hasConflict: conflicts.length > 0,
|
||||
|
||||
@@ -7,10 +7,71 @@ import type {
|
||||
import {
|
||||
consolidateConflictsByPackage,
|
||||
createBannedConflict,
|
||||
createPendingConflict
|
||||
createPendingConflict,
|
||||
evaluateCompatibility
|
||||
} from '@/workbench/extensions/manager/utils/conflictUtils'
|
||||
|
||||
describe('conflictUtils', () => {
|
||||
describe('evaluateCompatibility', () => {
|
||||
const incompatibleEnv = {
|
||||
comfyui_version: '0.3.0',
|
||||
frontend_version: '1.0.0',
|
||||
os: 'darwin',
|
||||
accelerator: 'mps'
|
||||
}
|
||||
|
||||
it('emits conflicts in canonical order when all six checks fail', () => {
|
||||
const conflicts = evaluateCompatibility(
|
||||
{
|
||||
supported_comfyui_version: '>=1.0.0',
|
||||
supported_comfyui_frontend_version: '>=2.0.0',
|
||||
supported_os: ['Linux'],
|
||||
supported_accelerators: ['CUDA'],
|
||||
isBanned: true,
|
||||
isPending: true
|
||||
},
|
||||
incompatibleEnv
|
||||
)
|
||||
|
||||
expect(conflicts.map((conflict) => conflict.type)).toEqual([
|
||||
'comfyui_version',
|
||||
'frontend_version',
|
||||
'os',
|
||||
'accelerator',
|
||||
'banned',
|
||||
'pending'
|
||||
])
|
||||
})
|
||||
|
||||
it('adds a banned conflict only when isBanned is true', () => {
|
||||
const compatibleInput = {
|
||||
supported_comfyui_version: undefined,
|
||||
supported_comfyui_frontend_version: undefined,
|
||||
supported_os: undefined,
|
||||
supported_accelerators: undefined,
|
||||
isPending: false
|
||||
}
|
||||
|
||||
const withoutBan = evaluateCompatibility(
|
||||
{ ...compatibleInput, isBanned: false },
|
||||
incompatibleEnv
|
||||
)
|
||||
expect(withoutBan).toEqual([])
|
||||
|
||||
const withBan = evaluateCompatibility(
|
||||
{ ...compatibleInput, isBanned: true },
|
||||
incompatibleEnv
|
||||
)
|
||||
expect(withBan).toEqual([
|
||||
{
|
||||
type: 'banned',
|
||||
current_value: 'installed',
|
||||
required_value: 'not_banned'
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('createBannedConflict', () => {
|
||||
it('should return banned conflict when isBanned is true', () => {
|
||||
const result = createBannedConflict(true)
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import { groupBy, uniqBy } from 'es-toolkit/compat'
|
||||
|
||||
import { normalizePackId } from '@/utils/packUtils'
|
||||
import type {
|
||||
RegistryAccelerator,
|
||||
RegistryOS
|
||||
} from '@/workbench/extensions/manager/types/compatibility.types'
|
||||
import type {
|
||||
ConflictDetail,
|
||||
ConflictDetectionResult
|
||||
ConflictDetectionResult,
|
||||
SystemEnvironment
|
||||
} from '@/workbench/extensions/manager/types/conflictDetectionTypes'
|
||||
import {
|
||||
checkAcceleratorCompatibility,
|
||||
checkOSCompatibility
|
||||
} from '@/workbench/extensions/manager/utils/systemCompatibility'
|
||||
import { checkVersionCompatibility } from '@/workbench/extensions/manager/utils/versionUtil'
|
||||
|
||||
/**
|
||||
* Checks for banned package status conflicts.
|
||||
@@ -38,6 +48,69 @@ export function createPendingConflict(
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalized compatibility inputs for a single package, produced by each call
|
||||
* site from its own source shape. Banned/pending are pre-derived booleans
|
||||
* because the two callers read different enums (see {@link evaluateCompatibility}).
|
||||
*/
|
||||
export interface CompatibilityInput {
|
||||
supported_os?: RegistryOS[]
|
||||
supported_accelerators?: RegistryAccelerator[]
|
||||
supported_comfyui_version?: string
|
||||
supported_comfyui_frontend_version?: string
|
||||
isBanned: boolean
|
||||
isPending: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the six compatibility leaf checks and collects the conflicts that fire.
|
||||
*
|
||||
* Canonical order = comfyui_version → frontend_version → OS → accelerator →
|
||||
* banned → pending. This is the order surfaced by the primary conflict dialog
|
||||
* (analyzePackageConflicts → runFullConflictAnalysis → WarningTabPanel); every
|
||||
* consumer filters conflicts by `.type`, so the order is cosmetic only.
|
||||
*/
|
||||
export function evaluateCompatibility(
|
||||
input: CompatibilityInput,
|
||||
env: Pick<
|
||||
SystemEnvironment,
|
||||
'comfyui_version' | 'frontend_version' | 'os' | 'accelerator'
|
||||
>
|
||||
): ConflictDetail[] {
|
||||
const conflicts: ConflictDetail[] = []
|
||||
|
||||
const versionConflict = checkVersionCompatibility(
|
||||
'comfyui_version',
|
||||
env.comfyui_version,
|
||||
input.supported_comfyui_version
|
||||
)
|
||||
if (versionConflict) conflicts.push(versionConflict)
|
||||
|
||||
const frontendConflict = checkVersionCompatibility(
|
||||
'frontend_version',
|
||||
env.frontend_version,
|
||||
input.supported_comfyui_frontend_version
|
||||
)
|
||||
if (frontendConflict) conflicts.push(frontendConflict)
|
||||
|
||||
const osConflict = checkOSCompatibility(input.supported_os, env.os)
|
||||
if (osConflict) conflicts.push(osConflict)
|
||||
|
||||
const acceleratorConflict = checkAcceleratorCompatibility(
|
||||
input.supported_accelerators,
|
||||
env.accelerator
|
||||
)
|
||||
if (acceleratorConflict) conflicts.push(acceleratorConflict)
|
||||
|
||||
const bannedConflict = createBannedConflict(input.isBanned)
|
||||
if (bannedConflict) conflicts.push(bannedConflict)
|
||||
|
||||
const pendingConflict = createPendingConflict(input.isPending)
|
||||
if (pendingConflict) conflicts.push(pendingConflict)
|
||||
|
||||
return conflicts
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups and deduplicates conflicts by normalized package name.
|
||||
* Consolidates multiple conflict sources (registry checks, import failures, disabled packages with version suffix)
|
||||
|
||||
Reference in New Issue
Block a user