Add auto_open_on_missing setting to control resolver auto-launch

This commit is contained in:
Dariusz L
2026-07-19 15:21:04 +02:00
parent a4875a607b
commit 0047514f7c
5 changed files with 68 additions and 1 deletions
+4
View File
@@ -30,6 +30,7 @@ SETTINGS_SCHEMA: List[Dict[str, Any]] = [
{ "serverKey": "auto_fill_base_model", "localKey": "ModelResolver.autoFillBaseModel", "type": "boolean", "default": True },
{ "serverKey": "auto_fill_subfolder", "localKey": "ModelResolver.autoFillSubfolder", "type": "boolean", "default": True },
{ "serverKey": "auto_refresh_comfy_models_after_apply", "localKey": "ModelResolver.autoRefreshComfyModelsAfterApply", "type": "boolean", "default": True },
{ "serverKey": "auto_open_on_missing", "localKey": "ModelResolver.autoOpenOnMissing", "type": "boolean", "default": False },
{ "serverKey": "workflow_hash_metadata_enabled", "localKey": "ModelResolver.workflowHashMetadataEnabled", "type": "boolean", "default": True },
{ "serverKey": "workflow_dependency_marker_enabled", "localKey": "ModelResolver.workflowDependencyMarkerEnabled", "type": "boolean", "default": False },
{ "serverKey": "download_backend", "localKey": "ModelResolver.downloadBackend", "type": "backend", "default": "python" },
@@ -192,6 +193,9 @@ def normalize_settings(settings: Optional[Mapping[str, Any]]) -> Dict[str, Any]:
data["auto_refresh_comfy_models_after_apply"] = bool_setting(
data.get("auto_refresh_comfy_models_after_apply"), True
)
data["auto_open_on_missing"] = bool_setting(
data.get("auto_open_on_missing"), False
)
data["download_path_mode"] = normalize_download_path_mode(
data.get("download_path_mode"), data.get("auto_fill_subfolder")
)
@@ -9,6 +9,14 @@ const queueMethodsSource = fs.readFileSync(
path.join(projectRoot, 'web/resolver/actions/queue_methods.js'),
'utf8'
);
const modelResolverSource = fs.readFileSync(
path.join(projectRoot, 'web/resolver/model_resolver.js'),
'utf8'
);
const optionsMethodsSource = fs.readFileSync(
path.join(projectRoot, 'web/resolver/views/options_methods.js'),
'utf8'
);
const resolveDownloadMethodsSource = fs.readFileSync(
path.join(projectRoot, 'web/resolver/actions/resolve_download_methods.js'),
'utf8'
@@ -662,6 +670,41 @@ test('active download refresh preserves existing cards for hover and tooltip sta
assert.match(queueMethodsSource, /patchDownloadsPanelElement\(currentElement, nextElement\)/);
});
test('automatic opening for missing models is disabled by default', () => {
const isAutoOpenEnabled = eval(`(${extractMethod(modelResolverSource, 'isAutoOpenEnabled')})`);
const previousLocalStorageDescriptor = Object.getOwnPropertyDescriptor(globalThis, 'localStorage');
const setStoredValue = value => {
Object.defineProperty(globalThis, 'localStorage', {
configurable: true,
value: { getItem: () => value },
});
};
try {
setStoredValue(null);
assert.equal(isAutoOpenEnabled(), false);
setStoredValue('false');
assert.equal(isAutoOpenEnabled(), false);
setStoredValue('true');
assert.equal(isAutoOpenEnabled(), true);
} finally {
if (previousLocalStorageDescriptor) {
Object.defineProperty(globalThis, 'localStorage', previousLocalStorageDescriptor);
} else delete globalThis.localStorage;
}
});
test('automatic opening remains conditional on unresolved models', () => {
assert.match(
modelResolverSource,
/if \(data\.total_missing > 0\) \{[\s\S]*?this\.openResolverManager\(\);/
);
assert.match(optionsMethodsSource, /id="mr-options-auto-open-on-missing"/);
assert.match(optionsMethodsSource, /auto_open_on_missing: Boolean\(autoOpenOnMissingInput\?\.checked\)/);
});
test('active workflow label prefers selected ComfyUI workflow tab name over route hash', () => {
const cleanWorkflowLabel = eval(`(${extractMethod(queueMethodsSource, 'cleanWorkflowLabel')})`);
const getWorkflowLabelFromActiveTabElement = eval(`(${extractMethod(queueMethodsSource, 'getWorkflowLabelFromActiveTabElement')})`);
+8
View File
@@ -24,6 +24,14 @@ class SettingsTests(unittest.TestCase):
]
)
def test_auto_open_on_missing_defaults_to_disabled(self):
self.assertFalse(normalize_settings({})["auto_open_on_missing"])
self.assertTrue(
normalize_settings({"auto_open_on_missing": "true"})[
"auto_open_on_missing"
]
)
def test_sanitize_folder_name(self):
self.assertEqual(sanitize_folder_name("valid_name"), "valid_name")
self.assertEqual(sanitize_folder_name("name/with\\slashes"), "name_with_slashes")
+1 -1
View File
@@ -1066,7 +1066,7 @@ export class ModelResolver {
* Check if auto-open preference is enabled
*/
isAutoOpenEnabled() {
return localStorage.getItem('ModelResolver.autoOpenOnMissing') !== 'false';
return localStorage.getItem('ModelResolver.autoOpenOnMissing') === 'true';
}
+12
View File
@@ -409,6 +409,15 @@ export const optionsMethods = {
<span class="mr-options-switch"></span>
</span>
</label>
<label class="mr-options-toggle-row">
<div class="mr-options-toggle-copy">
<span class="mr-options-toggle-title">Open when a workflow has missing models <span class="mr-tooltip-badge" data-tooltip="When enabled, loading a workflow opens Model Resolver only after analysis detects unresolved models. This option is disabled by default.">?</span></span>
</div>
<span class="mr-options-toggle-control">
<input id="mr-options-auto-open-on-missing" class="mr-options-switch-input" type="checkbox" ${tokens.auto_open_on_missing ? 'checked' : ''}>
<span class="mr-options-switch"></span>
</span>
</label>
<label class="mr-options-toggle-row">
<div class="mr-options-toggle-copy">
<span class="mr-options-toggle-title">Embed workflow hashes <span class="mr-tooltip-badge" data-tooltip="Adds SHA256 metadata for models used in saved workflows and image workflow JSON, so renamed files can be resolved by hash later.">?</span></span>
@@ -900,6 +909,7 @@ export const optionsMethods = {
const autoFillBaseModelInput = this.contentElement.querySelector('#mr-options-auto-fill-base-model');
const autoFillSubfolderInput = this.contentElement.querySelector('#mr-options-auto-fill-subfolder');
const autoRefreshComfyModelsInput = this.contentElement.querySelector('#mr-options-auto-refresh-comfy-models');
const autoOpenOnMissingInput = this.contentElement.querySelector('#mr-options-auto-open-on-missing');
const workflowHashMetadataInput = this.contentElement.querySelector('#mr-options-workflow-hash-metadata');
const workflowDependencyMarkerInput = this.contentElement.querySelector('#mr-options-workflow-dependency-marker');
const addDependencyNodeBtn = this.contentElement.querySelector('#mr-options-add-dependency-node');
@@ -1027,6 +1037,7 @@ export const optionsMethods = {
autoFillBaseModelInput,
autoFillSubfolderInput,
autoRefreshComfyModelsInput,
autoOpenOnMissingInput,
workflowHashMetadataInput,
workflowDependencyMarkerInput,
downloadBackendInput,
@@ -3425,6 +3436,7 @@ export const optionsMethods = {
auto_fill_base_model: Boolean(autoFillBaseModelInput?.checked),
auto_fill_subfolder: Boolean(autoFillSubfolderInput?.checked),
auto_refresh_comfy_models_after_apply: Boolean(autoRefreshComfyModelsInput?.checked),
auto_open_on_missing: Boolean(autoOpenOnMissingInput?.checked),
workflow_hash_metadata_enabled: Boolean(workflowHashMetadataInput?.checked),
workflow_dependency_marker_enabled: Boolean(workflowDependencyMarkerInput?.checked),
download_backend: downloadBackend,