Skip to content

Commit 76bc089

Browse files
christian-byrnewebfiltered
authored andcommitted
[bugfix] Filter model metadata by current widget selection (Comfy-Org#4021)
Co-authored-by: filtered <[email protected]>
1 parent 08994e8 commit 76bc089

File tree

5 files changed

+377
-4
lines changed

5 files changed

+377
-4
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"last_node_id": 1,
3+
"last_link_id": 0,
4+
"nodes": [
5+
{
6+
"id": 1,
7+
"type": "CheckpointLoaderSimple",
8+
"pos": [256, 256],
9+
"size": [315, 98],
10+
"flags": {},
11+
"order": 0,
12+
"mode": 0,
13+
"inputs": [],
14+
"outputs": [
15+
{
16+
"name": "MODEL",
17+
"type": "MODEL",
18+
"links": null
19+
},
20+
{
21+
"name": "CLIP",
22+
"type": "CLIP",
23+
"links": null
24+
},
25+
{
26+
"name": "VAE",
27+
"type": "VAE",
28+
"links": null
29+
}
30+
],
31+
"properties": {
32+
"Node name for S&R": "CheckpointLoaderSimple",
33+
"models": [
34+
{
35+
"name": "outdated_model.safetensors",
36+
"url": "http://localhost:8188/api/devtools/fake_model.safetensors",
37+
"directory": "text_encoders"
38+
},
39+
{
40+
"name": "another_outdated_model.safetensors",
41+
"url": "http://localhost:8188/api/devtools/fake_model.safetensors",
42+
"directory": "text_encoders"
43+
}
44+
]
45+
},
46+
"widgets_values": ["current_selected_model.safetensors"]
47+
}
48+
],
49+
"links": [],
50+
"groups": [],
51+
"config": {},
52+
"extra": {
53+
"ds": {
54+
"offset": [0, 0],
55+
"scale": 1
56+
}
57+
},
58+
"version": 0.4
59+
}

browser_tests/tests/dialog.spec.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ test.describe('Missing models warning', () => {
103103
}
104104
])
105105
}
106-
comfyPage.page.route(
106+
await comfyPage.page.route(
107107
'**/api/experiment/models',
108108
(route) => route.fulfill(modelFoldersRes),
109109
{ times: 1 }
@@ -121,7 +121,7 @@ test.describe('Missing models warning', () => {
121121
}
122122
])
123123
}
124-
comfyPage.page.route(
124+
await comfyPage.page.route(
125125
'**/api/experiment/models/text_encoders',
126126
(route) => route.fulfill(clipModelsRes),
127127
{ times: 1 }
@@ -133,6 +133,18 @@ test.describe('Missing models warning', () => {
133133
await expect(missingModelsWarning).not.toBeVisible()
134134
})
135135

136+
test('Should not display warning when model metadata exists but widget values have changed', async ({
137+
comfyPage
138+
}) => {
139+
// This tests the scenario where outdated model metadata exists in the workflow
140+
// but the actual selected models (widget values) have changed
141+
await comfyPage.loadWorkflow('model_metadata_widget_mismatch')
142+
143+
// The missing models warning should NOT appear
144+
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
145+
await expect(missingModelsWarning).not.toBeVisible()
146+
})
147+
136148
// Flaky test after parallelization
137149
// https://github.com/Comfy-Org/ComfyUI_frontend/pull/1400
138150
test.skip('Should download missing model when clicking download button', async ({

src/scripts/app.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import {
6363
findLegacyRerouteNodes,
6464
noNativeReroutes
6565
} from '@/utils/migration/migrateReroute'
66+
import { getSelectedModelsMetadata } from '@/utils/modelMetadataUtil'
6667
import { deserialiseAndCreate } from '@/utils/vintageClipboard'
6768

6869
import { type ComfyApi, PromptExecutionError, api } from './api'
@@ -1209,8 +1210,10 @@ export class ComfyApp {
12091210
}
12101211

12111212
// Collect models metadata from node
1212-
if (n.properties?.models?.length)
1213-
embeddedModels.push(...n.properties.models)
1213+
const selectedModels = getSelectedModelsMetadata(n)
1214+
if (selectedModels?.length) {
1215+
embeddedModels.push(...selectedModels)
1216+
}
12141217
}
12151218

12161219
// Merge models from the workflow's root-level 'models' field

src/utils/modelMetadataUtil.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { ModelFile } from '@/schemas/comfyWorkflowSchema'
2+
3+
/**
4+
* Gets models from the node's `properties.models` field, excluding those
5+
* not currently selected in at least 1 of the node's widget values.
6+
*
7+
* @example
8+
* ```ts
9+
* const node = {
10+
* type: 'CheckpointLoaderSimple',
11+
* widgets_values: ['model1', 'model2'],
12+
* properties: { models: [{ name: 'model1' }, { name: 'model2' }, { name: 'model3' }] }
13+
* ... other properties
14+
* }
15+
* const selectedModels = getSelectedModelsMetadata(node)
16+
* // selectedModels = [{ name: 'model1' }, { name: 'model2' }]
17+
* ```
18+
*
19+
* @param node - The workflow node to process
20+
* @returns Filtered array containing only models that are currently selected
21+
*/
22+
export function getSelectedModelsMetadata(node: {
23+
type: string
24+
widgets_values?: unknown[] | Record<string, unknown>
25+
properties?: { models?: ModelFile[] }
26+
}): ModelFile[] | undefined {
27+
try {
28+
if (!node.properties?.models?.length) return
29+
if (!node.widgets_values) return
30+
31+
const widgetValues = Array.isArray(node.widgets_values)
32+
? node.widgets_values
33+
: Object.values(node.widgets_values)
34+
35+
if (!widgetValues.length) return
36+
37+
const stringWidgetValues = new Set<string>()
38+
for (const widgetValue of widgetValues) {
39+
if (typeof widgetValue === 'string' && widgetValue.trim()) {
40+
stringWidgetValues.add(widgetValue)
41+
}
42+
}
43+
44+
// Return the node's models that are present in the widget values
45+
return node.properties.models.filter((model) =>
46+
stringWidgetValues.has(model.name)
47+
)
48+
} catch (error) {
49+
console.error('Error filtering models by current selection:', error)
50+
}
51+
}

0 commit comments

Comments
 (0)