Files
DemonGatanjieuandClaude Opus 5.5 c41af60cd9 Tell the AI what loads a model, file model patches right, add gallery pictures to messages
- model_kind: Anima LLLite, Qwen-Image block-wise and Z-Image Fun ControlNets (and other
  ModelPatchLoader files) go to model_patches, not controlnet; import and Tidy follow.
- api/mcp_model_use.py: search_models / get_model say which node types load each model, or
  where a misfiled one belongs; move_model moves it there behind a new "files" gate (asks by
  default, never overwrites).
- An empty drop-down in add_node says ComfyUI found no file; the task tab switch is no longer
  logged as the user's canvas change.
- The folded task list stays while the pointer is in the box around its button and the list.
- The message box's picture button picks gallery pictures; "@" offers the gallery's newest and
  searches it as you type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:50:57 +08:00

45 lines
2.1 KiB
JavaScript

const PHYSICAL_RENAME_PROTECTED_TYPES = new Set([
'vae',
'vae_approx',
'clip',
'text_encoders',
'clip_vision',
]);
// Scanner coverage is separate. These categories may be scanned, but automatic
// Model Check redirection requires workflow-carried cryptographic identity.
const HASH_ONLY_RECOVERY_TYPES = new Set([
'vae',
'vae_approx',
'clip',
'text_encoders',
'clip_vision',
]);
export function isPhysicalRenameProtectedType(folderType) {
return PHYSICAL_RENAME_PROTECTED_TYPES.has(String(folderType || '').trim().toLowerCase());
}
export function inferModelFolderTypes(node, widget) {
const widgetName = String(widget?.name || '').toLowerCase();
const nodeType = String(node?.type || '').toLowerCase();
const key = `${widgetName} ${nodeType}`;
if (nodeType === 'modelpatchloader') return ['model_patches'];
if (key.includes('clip_vision') || key.includes('clip vision') || nodeType.includes('clipvision')) return ['clip_vision'];
if (key.includes('vae_approx') || key.includes('vae approx')) return ['vae_approx'];
if (widgetName.includes('vae') || nodeType === 'vaeloader' || key.includes('vae loader')) return ['vae'];
if (widgetName.includes('lora') || key.includes('lora')) return ['loras'];
if (widgetName.includes('control_net') || widgetName.includes('controlnet') || key.includes('controlnet')) return ['controlnet'];
if (widgetName.includes('ckpt') || widgetName.includes('checkpoint') || key.includes('checkpoint')) return ['checkpoints'];
if (widgetName.includes('unet') || widgetName.includes('diffusion_model') || key.includes('unet loader')) return ['diffusion_models', 'unet'];
if (widgetName.includes('clip_name') || widgetName.includes('text_encoder') || nodeType.includes('cliploader')) return ['clip', 'text_encoders'];
if (nodeType.includes('upscalemodel') || widgetName.includes('upscale_model')) return ['upscale_models'];
return [];
}
export function requiresHashForModelRecovery(node, widget) {
const types = inferModelFolderTypes(node, widget);
return types.length > 0 && types.every(type => HASH_ONLY_RECOVERY_TYPES.has(type));
}