mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 19:21:54 +00:00
[Manager] Fix package version matching in conflict detection (#4530)
Co-authored-by: Jin Yi <jin12cc@gmail.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -252,20 +252,25 @@ const getVersionData = (version: string) => {
|
|||||||
nodePack.supported_comfyui_frontend_version,
|
nodePack.supported_comfyui_frontend_version,
|
||||||
supported_python_version:
|
supported_python_version:
|
||||||
(latestVersionData && 'supported_python_version' in latestVersionData
|
(latestVersionData && 'supported_python_version' in latestVersionData
|
||||||
? latestVersionData.supported_python_version as string | undefined
|
? (latestVersionData.supported_python_version as string | undefined)
|
||||||
: undefined) ??
|
: undefined) ??
|
||||||
('supported_python_version' in nodePack
|
('supported_python_version' in nodePack
|
||||||
? nodePack.supported_python_version as string | undefined
|
? (nodePack.supported_python_version as string | undefined)
|
||||||
: undefined),
|
: undefined),
|
||||||
is_banned:
|
is_banned:
|
||||||
(latestVersionData && 'is_banned' in latestVersionData
|
(latestVersionData && 'is_banned' in latestVersionData
|
||||||
? latestVersionData.is_banned as boolean | undefined
|
? (latestVersionData.is_banned as boolean | undefined)
|
||||||
: undefined) ?? ('is_banned' in nodePack ? nodePack.is_banned as boolean | undefined : false),
|
: undefined) ??
|
||||||
|
('is_banned' in nodePack
|
||||||
|
? (nodePack.is_banned as boolean | undefined)
|
||||||
|
: false),
|
||||||
has_registry_data:
|
has_registry_data:
|
||||||
(latestVersionData && 'has_registry_data' in latestVersionData
|
(latestVersionData && 'has_registry_data' in latestVersionData
|
||||||
? latestVersionData.has_registry_data as boolean | undefined
|
? (latestVersionData.has_registry_data as boolean | undefined)
|
||||||
: undefined) ??
|
: undefined) ??
|
||||||
('has_registry_data' in nodePack ? nodePack.has_registry_data as boolean | undefined : false)
|
('has_registry_data' in nodePack
|
||||||
|
? (nodePack.has_registry_data as boolean | undefined)
|
||||||
|
: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +286,7 @@ const getVersionData = (version: string) => {
|
|||||||
nodePack.supported_comfyui_frontend_version, // Use latest known requirement
|
nodePack.supported_comfyui_frontend_version, // Use latest known requirement
|
||||||
supported_python_version:
|
supported_python_version:
|
||||||
'supported_python_version' in nodePack
|
'supported_python_version' in nodePack
|
||||||
? nodePack.supported_python_version as string | undefined
|
? (nodePack.supported_python_version as string | undefined)
|
||||||
: undefined,
|
: undefined,
|
||||||
is_banned: false, // Nightly versions from repositories are typically not banned
|
is_banned: false, // Nightly versions from repositories are typically not banned
|
||||||
has_registry_data: false // Nightly doesn't come from registry
|
has_registry_data: false // Nightly doesn't come from registry
|
||||||
@@ -299,12 +304,15 @@ const getVersionData = (version: string) => {
|
|||||||
versionData.supported_comfyui_frontend_version,
|
versionData.supported_comfyui_frontend_version,
|
||||||
supported_python_version:
|
supported_python_version:
|
||||||
'supported_python_version' in versionData
|
'supported_python_version' in versionData
|
||||||
? versionData.supported_python_version as string | undefined
|
? (versionData.supported_python_version as string | undefined)
|
||||||
: undefined,
|
: undefined,
|
||||||
is_banned: 'is_banned' in versionData ? versionData.is_banned as boolean | undefined : false,
|
is_banned:
|
||||||
|
'is_banned' in versionData
|
||||||
|
? (versionData.is_banned as boolean | undefined)
|
||||||
|
: false,
|
||||||
has_registry_data:
|
has_registry_data:
|
||||||
'has_registry_data' in versionData
|
'has_registry_data' in versionData
|
||||||
? versionData.has_registry_data as boolean | undefined
|
? (versionData.has_registry_data as boolean | undefined)
|
||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,11 +326,16 @@ const getVersionData = (version: string) => {
|
|||||||
nodePack.supported_comfyui_frontend_version,
|
nodePack.supported_comfyui_frontend_version,
|
||||||
supported_python_version:
|
supported_python_version:
|
||||||
'supported_python_version' in nodePack
|
'supported_python_version' in nodePack
|
||||||
? nodePack.supported_python_version as string | undefined
|
? (nodePack.supported_python_version as string | undefined)
|
||||||
: undefined,
|
: undefined,
|
||||||
is_banned: 'is_banned' in nodePack ? nodePack.is_banned as boolean | undefined : false,
|
is_banned:
|
||||||
|
'is_banned' in nodePack
|
||||||
|
? (nodePack.is_banned as boolean | undefined)
|
||||||
|
: false,
|
||||||
has_registry_data:
|
has_registry_data:
|
||||||
'has_registry_data' in nodePack ? nodePack.has_registry_data as boolean | undefined : false
|
'has_registry_data' in nodePack
|
||||||
|
? (nodePack.has_registry_data as boolean | undefined)
|
||||||
|
: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const { nodePack, hasConflict } = defineProps<{
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { isPackEnabled, enablePack, disablePack } = useComfyManagerStore()
|
const { isPackEnabled, enablePack, disablePack } = useComfyManagerStore()
|
||||||
const conflictStore = useConflictDetectionStore()
|
const { getConflictsForPackageByID } = useConflictDetectionStore()
|
||||||
const { showNodeConflictDialog } = useDialogService()
|
const { showNodeConflictDialog } = useDialogService()
|
||||||
const { acknowledgeConflict, isConflictAcknowledged } =
|
const { acknowledgeConflict, isConflictAcknowledged } =
|
||||||
useConflictAcknowledgment()
|
useConflictAcknowledgment()
|
||||||
@@ -87,7 +87,7 @@ const handleToggle = async (enable: boolean, skipConflictCheck = false) => {
|
|||||||
|
|
||||||
// Check for conflicts when enabling
|
// Check for conflicts when enabling
|
||||||
if (enable && hasConflict && !skipConflictCheck) {
|
if (enable && hasConflict && !skipConflictCheck) {
|
||||||
const conflicts = conflictStore.getConflictsForPackage(nodePack.id || '')
|
const conflicts = getConflictsForPackageByID(nodePack.id || '')
|
||||||
if (conflicts) {
|
if (conflicts) {
|
||||||
// Check if conflicts have been acknowledged
|
// Check if conflicts have been acknowledged
|
||||||
const hasUnacknowledgedConflicts = conflicts.conflicts.some(
|
const hasUnacknowledgedConflicts = conflicts.conflicts.some(
|
||||||
@@ -141,7 +141,7 @@ const onToggle = debounce(
|
|||||||
|
|
||||||
// Show conflict modal when warning icon is clicked
|
// Show conflict modal when warning icon is clicked
|
||||||
const showConflictModal = () => {
|
const showConflictModal = () => {
|
||||||
const conflicts = conflictStore.getConflictsForPackage(nodePack.id || '')
|
const conflicts = getConflictsForPackageByID(nodePack.id || '')
|
||||||
if (conflicts) {
|
if (conflicts) {
|
||||||
showNodeConflictDialog({
|
showNodeConflictDialog({
|
||||||
conflictedPackages: [conflicts],
|
conflictedPackages: [conflicts],
|
||||||
|
|||||||
@@ -62,12 +62,15 @@ const nodeNames = computed(() => {
|
|||||||
const activeTab = ref('description')
|
const activeTab = ref('description')
|
||||||
|
|
||||||
// Watch for compatibility issues and automatically switch to warning tab
|
// Watch for compatibility issues and automatically switch to warning tab
|
||||||
watchEffect(() => {
|
watchEffect(
|
||||||
if (hasCompatibilityIssues) {
|
() => {
|
||||||
activeTab.value = 'warning'
|
if (hasCompatibilityIssues) {
|
||||||
} else if (activeTab.value === 'warning') {
|
activeTab.value = 'warning'
|
||||||
// If currently on warning tab but no issues, switch to description
|
} else if (activeTab.value === 'warning') {
|
||||||
activeTab.value = 'description'
|
// If currently on warning tab but no issues, switch to description
|
||||||
}
|
activeTab.value = 'description'
|
||||||
}, { flush: 'post' })
|
}
|
||||||
|
},
|
||||||
|
{ flush: 'post' }
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -44,20 +44,16 @@ const formattedDownloads = computed(() =>
|
|||||||
nodePack.downloads ? n(nodePack.downloads) : ''
|
nodePack.downloads ? n(nodePack.downloads) : ''
|
||||||
)
|
)
|
||||||
|
|
||||||
const conflictStore = useConflictDetectionStore()
|
const { getConflictsForPackageByID } = useConflictDetectionStore()
|
||||||
const { checkVersionCompatibility } = useConflictDetection()
|
const { checkVersionCompatibility } = useConflictDetection()
|
||||||
|
|
||||||
// TODO: Package version mismatch issue - Package IDs include version suffixes (@1_0_3)
|
|
||||||
// but UI searches without version. This causes conflict detection failures.
|
|
||||||
// Once getConflictsForPackage is improved to handle version matching properly,
|
|
||||||
// all the complex fallback logic below can be removed.
|
|
||||||
const hasConflict = computed(() => {
|
const hasConflict = computed(() => {
|
||||||
if (!nodePack.id) return false
|
if (!nodePack.id) return false
|
||||||
|
|
||||||
// For installed packages, check conflicts from store
|
// For installed packages, check conflicts from store
|
||||||
if (isInstalled.value) {
|
if (isInstalled.value) {
|
||||||
// Try exact match first
|
// Try exact match first
|
||||||
let conflicts = conflictStore.getConflictsForPackage(nodePack.id)
|
let conflicts = getConflictsForPackageByID(nodePack.id)
|
||||||
if (conflicts) return true
|
if (conflicts) return true
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ const { nodePack } = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { isPackInstalled } = useComfyManagerStore()
|
const { isPackInstalled } = useComfyManagerStore()
|
||||||
const conflictStore = useConflictDetectionStore()
|
const { getConflictsForPackageByID } = useConflictDetectionStore()
|
||||||
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
|
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
|
||||||
|
|
||||||
const packageConflicts = computed(() => {
|
const packageConflicts = computed(() => {
|
||||||
if (!nodePack.id || !isInstalled.value) return null
|
if (!nodePack.id || !isInstalled.value) return null
|
||||||
|
|
||||||
// For installed packages, check conflicts from store
|
// For installed packages, check conflicts from store
|
||||||
return conflictStore.getConflictsForPackage(nodePack.id)
|
return getConflictsForPackageByID(nodePack.id)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ export const useInstalledPacks = (options: UseNodePacksOptions = {}) => {
|
|||||||
packs.filter((pack) => comfyManagerStore.isPackInstalled(pack.id))
|
packs.filter((pack) => comfyManagerStore.isPackInstalled(pack.id))
|
||||||
|
|
||||||
const startFetchInstalled = async () => {
|
const startFetchInstalled = async () => {
|
||||||
await comfyManagerStore.refreshInstalledList()
|
// Only refresh if store doesn't have data yet
|
||||||
|
if (comfyManagerStore.installedPacksIds.size === 0) {
|
||||||
|
await comfyManagerStore.refreshInstalledList()
|
||||||
|
}
|
||||||
await startFetch()
|
await startFetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { uniqBy } from 'lodash'
|
import { uniqBy } from 'lodash'
|
||||||
import { computed, getCurrentInstance, onUnmounted, readonly, ref } from 'vue'
|
import { computed, getCurrentInstance, onUnmounted, readonly, ref } from 'vue'
|
||||||
|
|
||||||
|
import { useInstalledPacks } from '@/composables/nodePack/useInstalledPacks'
|
||||||
import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment'
|
import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import { useComfyManagerService } from '@/services/comfyManagerService'
|
import { useComfyManagerService } from '@/services/comfyManagerService'
|
||||||
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
||||||
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
|
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
|
||||||
import { useSystemStatsStore } from '@/stores/systemStatsStore'
|
import { useSystemStatsStore } from '@/stores/systemStatsStore'
|
||||||
import type { SystemStats } from '@/types'
|
import type { SystemStats } from '@/types'
|
||||||
@@ -20,7 +22,6 @@ import type {
|
|||||||
SupportedOS,
|
SupportedOS,
|
||||||
SystemEnvironment
|
SystemEnvironment
|
||||||
} from '@/types/conflictDetectionTypes'
|
} from '@/types/conflictDetectionTypes'
|
||||||
import type { components as ManagerComponents } from '@/types/generatedManagerTypes'
|
|
||||||
import {
|
import {
|
||||||
cleanVersion,
|
cleanVersion,
|
||||||
satisfiesVersion,
|
satisfiesVersion,
|
||||||
@@ -32,6 +33,16 @@ import {
|
|||||||
* Error-resilient and asynchronous to avoid affecting other components.
|
* Error-resilient and asynchronous to avoid affecting other components.
|
||||||
*/
|
*/
|
||||||
export function useConflictDetection() {
|
export function useConflictDetection() {
|
||||||
|
// Store references
|
||||||
|
const managerStore = useComfyManagerStore()
|
||||||
|
|
||||||
|
// Use installed packs composable instead of direct API calls
|
||||||
|
const {
|
||||||
|
startFetchInstalled,
|
||||||
|
installedPacks,
|
||||||
|
isReady: installedPacksReady
|
||||||
|
} = useInstalledPacks()
|
||||||
|
|
||||||
// State management
|
// State management
|
||||||
const isDetecting = ref(false)
|
const isDetecting = ref(false)
|
||||||
const lastDetectionTime = ref<string | null>(null)
|
const lastDetectionTime = ref<string | null>(null)
|
||||||
@@ -178,15 +189,17 @@ export function useConflictDetection() {
|
|||||||
*/
|
*/
|
||||||
async function fetchPackageRequirements(): Promise<NodePackRequirements[]> {
|
async function fetchPackageRequirements(): Promise<NodePackRequirements[]> {
|
||||||
try {
|
try {
|
||||||
// Step 1: Get locally installed packages
|
// Step 1: Use installed packs composable instead of direct API calls
|
||||||
const comfyManagerService = useComfyManagerService()
|
// This follows Christian's architecture suggestion to use computed properties
|
||||||
const installedNodes:
|
await startFetchInstalled() // Ensure data is loaded
|
||||||
| ManagerComponents['schemas']['InstalledPacksResponse']
|
|
||||||
| null = await comfyManagerService.listInstalledPacks()
|
|
||||||
|
|
||||||
if (!installedNodes) {
|
if (
|
||||||
|
!installedPacksReady.value ||
|
||||||
|
!installedPacks.value ||
|
||||||
|
installedPacks.value.length === 0
|
||||||
|
) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'[ConflictDetection] Unable to fetch installed package information'
|
'[ConflictDetection] No installed packages available from useInstalledPacks'
|
||||||
)
|
)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -200,34 +213,34 @@ export function useConflictDetection() {
|
|||||||
// Step 4: Fetch version-specific data in chunks to avoid overwhelming the Registry API
|
// Step 4: Fetch version-specific data in chunks to avoid overwhelming the Registry API
|
||||||
// - Each chunk processes up to 30 packages concurrently
|
// - Each chunk processes up to 30 packages concurrently
|
||||||
// - Results are stored in versionDataMap for later use
|
// - Results are stored in versionDataMap for later use
|
||||||
const entries = Object.entries(installedNodes)
|
// - Use installedPacks from useInstalledPacks composable
|
||||||
const chunkSize = 30 // 청크 크기
|
const chunkSize = 30
|
||||||
const versionDataMap = new Map<
|
const versionDataMap = new Map<
|
||||||
string,
|
string,
|
||||||
components['schemas']['NodeVersion']
|
components['schemas']['NodeVersion']
|
||||||
>()
|
>()
|
||||||
|
|
||||||
for (let i = 0; i < entries.length; i += chunkSize) {
|
for (let i = 0; i < installedPacks.value.length; i += chunkSize) {
|
||||||
const chunk = entries.slice(i, i + chunkSize)
|
const chunk = installedPacks.value.slice(i, i + chunkSize)
|
||||||
|
|
||||||
const fetchTasks = chunk.map(async ([packageName, nodeInfo]) => {
|
const fetchTasks = chunk.map(async (pack) => {
|
||||||
const typedNodeInfo: ManagerComponents['schemas']['ManagerPackInstalled'] =
|
// Use pack.id which should be the normalized ID from Registry
|
||||||
nodeInfo
|
const packageId = pack.id || ''
|
||||||
const version = typedNodeInfo.ver || 'latest'
|
const version = pack.latest_version?.version || 'latest'
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const versionData = await registryService.getPackByVersion(
|
const versionData = await registryService.getPackByVersion(
|
||||||
packageName,
|
packageId,
|
||||||
version,
|
version,
|
||||||
abortController.value?.signal
|
abortController.value?.signal
|
||||||
)
|
)
|
||||||
|
|
||||||
if (versionData) {
|
if (versionData) {
|
||||||
versionDataMap.set(packageName, versionData)
|
versionDataMap.set(packageId, versionData)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[ConflictDetection] Failed to fetch version data for ${packageName}@${version}:`,
|
`[ConflictDetection] Failed to fetch version data for ${packageId}@${version}:`,
|
||||||
error
|
error
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -237,21 +250,24 @@ export function useConflictDetection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Combine local installation data with Registry version data
|
// Step 5: Combine local installation data with Registry version data
|
||||||
|
// Use installedPacks from useInstalledPacks composable
|
||||||
const requirements: NodePackRequirements[] = []
|
const requirements: NodePackRequirements[] = []
|
||||||
|
|
||||||
for (const [packageName, nodeInfo] of Object.entries(installedNodes)) {
|
for (const pack of installedPacks.value) {
|
||||||
const typedNodeInfo: ManagerComponents['schemas']['ManagerPackInstalled'] =
|
const packageId = pack.id || ''
|
||||||
nodeInfo
|
const versionData = versionDataMap.get(packageId)
|
||||||
const versionData = versionDataMap.get(packageName)
|
|
||||||
|
// Check if package is enabled using store method
|
||||||
|
const isEnabled = managerStore.isPackEnabled(packageId)
|
||||||
|
|
||||||
if (versionData) {
|
if (versionData) {
|
||||||
// Combine local installation data with version-specific Registry data
|
// Combine local installation data with version-specific Registry data
|
||||||
const requirement: NodePackRequirements = {
|
const requirement: NodePackRequirements = {
|
||||||
// Basic package info
|
// Basic package info
|
||||||
package_id: packageName,
|
package_id: packageId,
|
||||||
package_name: packageName, // We don't need to fetch node info separately
|
package_name: pack.name || packageId,
|
||||||
installed_version: typedNodeInfo.ver || 'unknown',
|
installed_version: pack.latest_version?.version || 'unknown',
|
||||||
is_enabled: typedNodeInfo.enabled,
|
is_enabled: isEnabled,
|
||||||
|
|
||||||
// Version-specific compatibility data
|
// Version-specific compatibility data
|
||||||
supported_comfyui_version: versionData.supported_comfyui_version,
|
supported_comfyui_version: versionData.supported_comfyui_version,
|
||||||
@@ -266,12 +282,11 @@ export function useConflictDetection() {
|
|||||||
registry_status: undefined, // Node status - not critical for conflict detection
|
registry_status: undefined, // Node status - not critical for conflict detection
|
||||||
version_status: versionData.status,
|
version_status: versionData.status,
|
||||||
is_banned:
|
is_banned:
|
||||||
versionData.status === 'NodeVersionStatusBanned' ||
|
versionData.status === 'NodeVersionStatusBanned' || !isEnabled,
|
||||||
!typedNodeInfo.enabled,
|
|
||||||
ban_reason:
|
ban_reason:
|
||||||
versionData.status === 'NodeVersionStatusBanned'
|
versionData.status === 'NodeVersionStatusBanned'
|
||||||
? 'Version is banned in Registry'
|
? 'Version is banned in Registry'
|
||||||
: !typedNodeInfo.enabled
|
: !isEnabled
|
||||||
? 'Package is disabled locally'
|
? 'Package is disabled locally'
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|
||||||
@@ -283,19 +298,17 @@ export function useConflictDetection() {
|
|||||||
requirements.push(requirement)
|
requirements.push(requirement)
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[ConflictDetection] No Registry data found for ${packageName}, using fallback`
|
`[ConflictDetection] No Registry data found for ${packageId}, using fallback`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create fallback requirement without Registry data
|
// Create fallback requirement without Registry data
|
||||||
const fallbackRequirement: NodePackRequirements = {
|
const fallbackRequirement: NodePackRequirements = {
|
||||||
package_id: packageName,
|
package_id: packageId,
|
||||||
package_name: packageName,
|
package_name: pack.name || packageId,
|
||||||
installed_version: typedNodeInfo.ver || 'unknown',
|
installed_version: pack.latest_version?.version || 'unknown',
|
||||||
is_enabled: typedNodeInfo.enabled,
|
is_enabled: isEnabled,
|
||||||
is_banned: !typedNodeInfo.enabled,
|
is_banned: !isEnabled,
|
||||||
ban_reason: !typedNodeInfo.enabled
|
ban_reason: !isEnabled ? 'Package is disabled locally' : undefined,
|
||||||
? 'Package is disabled locally'
|
|
||||||
: undefined,
|
|
||||||
registry_fetch_time: new Date().toISOString(),
|
registry_fetch_time: new Date().toISOString(),
|
||||||
has_registry_data: false
|
has_registry_data: false
|
||||||
}
|
}
|
||||||
@@ -415,13 +428,15 @@ export function useConflictDetection() {
|
|||||||
try {
|
try {
|
||||||
const comfyManagerService = useComfyManagerService()
|
const comfyManagerService = useComfyManagerService()
|
||||||
|
|
||||||
// Get installed packages first
|
// Use installed packs from useInstalledPacks composable
|
||||||
const installedPacks = await comfyManagerService.listInstalledPacks(
|
if (
|
||||||
abortController.value?.signal
|
!installedPacksReady.value ||
|
||||||
)
|
!installedPacks.value ||
|
||||||
|
installedPacks.value.length === 0
|
||||||
if (!installedPacks) {
|
) {
|
||||||
console.warn('[ConflictDetection] No installed packages found')
|
console.warn(
|
||||||
|
'[ConflictDetection] No installed packages available from useInstalledPacks'
|
||||||
|
)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,27 +444,27 @@ export function useConflictDetection() {
|
|||||||
|
|
||||||
// Check each installed package for import failures
|
// Check each installed package for import failures
|
||||||
// Process in smaller batches to avoid overwhelming the API
|
// Process in smaller batches to avoid overwhelming the API
|
||||||
const packageNames = Object.keys(installedPacks)
|
const packageIds = installedPacks.value.map((pack) => pack.id)
|
||||||
const batchSize = 10
|
const batchSize = 10
|
||||||
|
|
||||||
for (let i = 0; i < packageNames.length; i += batchSize) {
|
for (let i = 0; i < packageIds.length; i += batchSize) {
|
||||||
const batch = packageNames.slice(i, i + batchSize)
|
const batch = packageIds.slice(i, i + batchSize)
|
||||||
|
|
||||||
const batchResults = await Promise.allSettled(
|
const batchResults = await Promise.allSettled(
|
||||||
batch.map(async (packageName) => {
|
batch.map(async (packageId) => {
|
||||||
try {
|
try {
|
||||||
// Try to get import failure info for this package
|
// Try to get import failure info for this package using normalized ID
|
||||||
const failInfo = await comfyManagerService.getImportFailInfo(
|
const failInfo = await comfyManagerService.getImportFailInfo(
|
||||||
{ cnr_id: packageName },
|
{ cnr_id: packageId },
|
||||||
abortController.value?.signal
|
abortController.value?.signal
|
||||||
)
|
)
|
||||||
|
|
||||||
if (failInfo) {
|
if (failInfo) {
|
||||||
console.log(
|
console.log(
|
||||||
`[ConflictDetection] Import failure found for ${packageName}:`,
|
`[ConflictDetection] Import failure found for ${packageId}:`,
|
||||||
failInfo
|
failInfo
|
||||||
)
|
)
|
||||||
return { packageName, failInfo }
|
return { packageId, failInfo }
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If API returns 400, it means no import failure info available
|
// If API returns 400, it means no import failure info available
|
||||||
@@ -462,7 +477,7 @@ export function useConflictDetection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.warn(
|
console.warn(
|
||||||
`[ConflictDetection] Failed to check import failure for ${packageName}:`,
|
`[ConflictDetection] Failed to check import failure for ${packageId}:`,
|
||||||
error
|
error
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -473,8 +488,8 @@ export function useConflictDetection() {
|
|||||||
// Process batch results
|
// Process batch results
|
||||||
batchResults.forEach((result) => {
|
batchResults.forEach((result) => {
|
||||||
if (result.status === 'fulfilled' && result.value) {
|
if (result.status === 'fulfilled' && result.value) {
|
||||||
const { packageName, failInfo } = result.value
|
const { packageId, failInfo } = result.value
|
||||||
importFailures[packageName] = failInfo
|
importFailures[packageId || ''] = failInfo
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -504,7 +519,7 @@ export function useConflictDetection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process import failures
|
// Process import failures
|
||||||
for (const [packageName, failureInfo] of Object.entries(importFailInfo)) {
|
for (const [packageId, failureInfo] of Object.entries(importFailInfo)) {
|
||||||
if (failureInfo && typeof failureInfo === 'object') {
|
if (failureInfo && typeof failureInfo === 'object') {
|
||||||
// Extract error information from Manager API response
|
// Extract error information from Manager API response
|
||||||
const errorMsg = failureInfo.msg || 'Unknown import error'
|
const errorMsg = failureInfo.msg || 'Unknown import error'
|
||||||
@@ -522,15 +537,15 @@ export function useConflictDetection() {
|
|||||||
]
|
]
|
||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
package_id: packageName,
|
package_id: packageId,
|
||||||
package_name: packageName,
|
package_name: packageId,
|
||||||
has_conflict: true,
|
has_conflict: true,
|
||||||
conflicts,
|
conflicts,
|
||||||
is_compatible: false
|
is_compatible: false
|
||||||
})
|
})
|
||||||
|
|
||||||
console.warn(
|
console.warn(
|
||||||
`[ConflictDetection] Python import failure detected for ${packageName}:`,
|
`[ConflictDetection] Python import failure detected for ${packageId}:`,
|
||||||
{
|
{
|
||||||
path: modulePath,
|
path: modulePath,
|
||||||
error: errorMsg,
|
error: errorMsg,
|
||||||
@@ -949,11 +964,14 @@ function mergeConflictsByPackageName(
|
|||||||
const mergedMap = new Map<string, ConflictDetectionResult>()
|
const mergedMap = new Map<string, ConflictDetectionResult>()
|
||||||
|
|
||||||
conflicts.forEach((conflict) => {
|
conflicts.forEach((conflict) => {
|
||||||
const packageName = conflict.package_name
|
// Normalize package name by removing version suffix (@1_0_3) for consistent merging
|
||||||
|
const normalizedPackageName = conflict.package_name.includes('@')
|
||||||
|
? conflict.package_name.substring(0, conflict.package_name.indexOf('@'))
|
||||||
|
: conflict.package_name
|
||||||
|
|
||||||
if (mergedMap.has(packageName)) {
|
if (mergedMap.has(normalizedPackageName)) {
|
||||||
// Package already exists, merge conflicts
|
// Package already exists, merge conflicts
|
||||||
const existing = mergedMap.get(packageName)!
|
const existing = mergedMap.get(normalizedPackageName)!
|
||||||
|
|
||||||
// Combine all conflicts, avoiding duplicates using lodash uniqBy for O(n) performance
|
// Combine all conflicts, avoiding duplicates using lodash uniqBy for O(n) performance
|
||||||
const allConflicts = [...existing.conflicts, ...conflict.conflicts]
|
const allConflicts = [...existing.conflicts, ...conflict.conflicts]
|
||||||
@@ -963,16 +981,20 @@ function mergeConflictsByPackageName(
|
|||||||
`${conflict.type}|${conflict.current_value}|${conflict.required_value}`
|
`${conflict.type}|${conflict.current_value}|${conflict.required_value}`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Update the existing entry
|
// Update the existing entry with normalized package name
|
||||||
mergedMap.set(packageName, {
|
mergedMap.set(normalizedPackageName, {
|
||||||
...existing,
|
...existing,
|
||||||
|
package_name: normalizedPackageName,
|
||||||
conflicts: uniqueConflicts,
|
conflicts: uniqueConflicts,
|
||||||
has_conflict: uniqueConflicts.length > 0,
|
has_conflict: uniqueConflicts.length > 0,
|
||||||
is_compatible: uniqueConflicts.length === 0
|
is_compatible: uniqueConflicts.length === 0
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// New package, add as-is
|
// New package, add with normalized package name
|
||||||
mergedMap.set(packageName, conflict)
|
mergedMap.set(normalizedPackageName, {
|
||||||
|
...conflict,
|
||||||
|
package_name: normalizedPackageName
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,6 @@ import type { SettingParams } from '@/types/settingTypes'
|
|||||||
* when they are no longer needed.
|
* when they are no longer needed.
|
||||||
*/
|
*/
|
||||||
export const CORE_SETTINGS: SettingParams[] = [
|
export const CORE_SETTINGS: SettingParams[] = [
|
||||||
{
|
|
||||||
id: 'Comfy.Memory.AllowManualUnload',
|
|
||||||
name: 'Allow manual unload of models and execution cache via user command',
|
|
||||||
type: 'hidden',
|
|
||||||
defaultValue: true,
|
|
||||||
versionAdded: '1.18.0'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'Comfy.Validation.Workflows',
|
id: 'Comfy.Validation.Workflows',
|
||||||
name: 'Validate workflows',
|
name: 'Validate workflows',
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const useConflictDetectionStore = defineStore(
|
|||||||
conflictedPackages.value.some((pkg) => pkg.has_conflict)
|
conflictedPackages.value.some((pkg) => pkg.has_conflict)
|
||||||
)
|
)
|
||||||
|
|
||||||
const getConflictsForPackage = computed(
|
const getConflictsForPackageByID = computed(
|
||||||
() => (packageId: string) =>
|
() => (packageId: string) =>
|
||||||
conflictedPackages.value.find((pkg) => pkg.package_id === packageId)
|
conflictedPackages.value.find((pkg) => pkg.package_id === packageId)
|
||||||
)
|
)
|
||||||
@@ -57,7 +57,7 @@ export const useConflictDetectionStore = defineStore(
|
|||||||
lastDetectionTime,
|
lastDetectionTime,
|
||||||
// Getters
|
// Getters
|
||||||
hasConflicts,
|
hasConflicts,
|
||||||
getConflictsForPackage,
|
getConflictsForPackageByID,
|
||||||
bannedPackages,
|
bannedPackages,
|
||||||
securityPendingPackages,
|
securityPendingPackages,
|
||||||
// Actions
|
// Actions
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ describe('useConflictDetectionStore', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('getConflictsForPackage', () => {
|
describe('getConflictsForPackageByID', () => {
|
||||||
it('should find package by exact ID match', () => {
|
it('should find package by exact ID match', () => {
|
||||||
const store = useConflictDetectionStore()
|
const store = useConflictDetectionStore()
|
||||||
store.setConflictedPackages(mockConflictedPackages)
|
store.setConflictedPackages(mockConflictedPackages)
|
||||||
|
|
||||||
const result = store.getConflictsForPackage('ComfyUI-Manager')
|
const result = store.getConflictsForPackageByID('ComfyUI-Manager')
|
||||||
|
|
||||||
expect(result).toBeDefined()
|
expect(result).toBeDefined()
|
||||||
expect(result?.package_id).toBe('ComfyUI-Manager')
|
expect(result?.package_id).toBe('ComfyUI-Manager')
|
||||||
@@ -99,7 +99,7 @@ describe('useConflictDetectionStore', () => {
|
|||||||
const store = useConflictDetectionStore()
|
const store = useConflictDetectionStore()
|
||||||
store.setConflictedPackages(mockConflictedPackages)
|
store.setConflictedPackages(mockConflictedPackages)
|
||||||
|
|
||||||
const result = store.getConflictsForPackage('non-existent-package')
|
const result = store.getConflictsForPackageByID('non-existent-package')
|
||||||
|
|
||||||
expect(result).toBeUndefined()
|
expect(result).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user