Files
DemonGatanjieuandClaude c9c9e5b21e Shorten the Ways panel, tell the ways from their own files, stop an LLLite that does not fit
- The Ways panel lists the ways that can run here as short rows that open,
  then the skills, and folds the ways lacking a pack or a model at the bottom.
- The staged_picture skill keeps the judgment only: the ways of its uses come
  from each block's "when", listed with the skill for what can run here. Its
  answer had passed the 3,800 bytes an AI app shows in the chat (3,991); a test
  keeps every skill under it.
- An Anima LLLite made for 28-block (2B) models stops a run on a 40-block
  (2.9B) one: lllite_fit counts both from the files' headers, the AI's run is
  refused with the nodes to change, and an example with a Tile opens on a model
  it fits. The warning written into four ways and two examples is removed.
- What holds for a model family is written once: the profile's notes go with
  each Anima example for an AI, the examples window says it once for the user;
  a pack two nodes come from is named once.
- The Tile upscale is want="tile", no longer the name of another use.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-10 16:25:22 +08:00

181 lines
12 KiB
Python

from . import (
activity_log, audio_catalog, folder_types, gallery_routes, materials, media_routes, model_catalog,
model_folder, model_media, model_metadata, model_resolution, model_type_listing, kept_images, quick_index, node_material, recipe_packages, recipes, scan_choice, scan_report, scan_summary,
local_guard, lora_info, mcp_server, model_download, model_import, model_placement, translation_routes, version_manager, tts_version, backup,
network_check, model_heads, model_usage, usage_ledger, sidecar_layout, ai_tasks_routes, snapshot_routes, workflow_saves, example_workflows,
model_guide, job_sheets, prompt_language, lllite_fit, description_translation, voice_covers,
)
from .scanner import *
from .config import *
from .notebooks import *
from .parameters import *
import os
from aiohttp import web
# ComfyUI serves the web folder under the plugin folder's own name, whatever it is called.
EXTENSION_STATIC_PREFIX = f'/extensions/{os.path.basename(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))}/'
@web.middleware
async def no_cache_extension_middleware(request, handler):
"""Make browsers revalidate this plugin's JS/CSS so a normal refresh picks up updates.
`no-cache` still allows 304 responses via ETag/Last-Modified. This replaces
per-import `?v=` query strings, which load a second module instance whenever
two files import the same module with different URLs.
"""
response = await handler(request)
if request.path.startswith(EXTENSION_STATIC_PREFIX):
response.headers['Cache-Control'] = 'no-cache'
return response
def setup_routes(app):
model_heads.keep_on_disk()
if hasattr(app, 'middlewares') and no_cache_extension_middleware not in app.middlewares:
app.middlewares.append(no_cache_extension_middleware)
# Other devices on the network may look; only this computer may change things (local_guard.py).
if hasattr(app, 'middlewares') and local_guard.local_only_middleware not in app.middlewares:
app.middlewares.append(local_guard.local_only_middleware)
app.router.add_get('/anomalous/access', local_guard.api_access)
app.router.add_post('/anomalous/snapshot_check', snapshot_routes.api_snapshot_check)
app.router.add_get('/anomalous/saves', workflow_saves.api_list)
app.router.add_get('/anomalous/saves/group', workflow_saves.api_group)
app.router.add_get('/anomalous/saves/workflow', workflow_saves.api_workflow)
app.router.add_post('/anomalous/saves/add', workflow_saves.api_add)
app.router.add_post('/anomalous/saves/update', workflow_saves.api_update)
app.router.add_post('/anomalous/saves/ran', workflow_saves.api_ran)
app.router.add_post('/anomalous/saves/remove', workflow_saves.api_remove)
app.router.add_post('/anomalous/saves/remove_group', workflow_saves.api_remove_group)
app.router.add_get('/anomalous/job_sheet', job_sheets.api_get)
app.router.add_get('/anomalous/job_sheet/workflow', job_sheets.api_workflow)
app.router.add_post('/anomalous/job_sheet/start', job_sheets.api_start)
app.router.add_post('/anomalous/job_sheet/report', job_sheets.api_report)
app.router.add_post('/anomalous/job_sheet/ask', job_sheets.api_ask)
app.router.add_post('/anomalous/job_sheet/clear', job_sheets.api_clear)
app.router.add_post('/anomalous/prompt_language', prompt_language.api_check)
app.router.add_post('/anomalous/lllite_fit', lllite_fit.api_check)
app.router.add_post('/anomalous/translate_description', description_translation.api_translate_description)
app.router.add_get('/anomalous/voice_covers', voice_covers.api_list)
app.router.add_get('/anomalous/voice_cover', voice_covers.api_get)
app.router.add_post('/anomalous/voice_cover', voice_covers.api_set)
app.router.add_post('/anomalous/voice_cover/remove', voice_covers.api_remove)
try:
folder_types.upgrade_folder_defaults()
except Exception as error:
print(f"[Anomalous Browser] Could not update the shown model folders: {error}")
app.router.add_get('/anomalous/folders', model_catalog.api_get_folders)
app.router.add_get('/anomalous/all_folder_types', folder_types.api_get_all_folder_types)
app.router.add_get('/anomalous/models', model_catalog.api_get_models)
app.router.add_get('/anomalous/type_models', model_type_listing.api_get_type_models)
app.router.add_get('/anomalous/all_scan_models', model_catalog.api_get_all_scan_models)
app.router.add_get('/anomalous/image', media_routes.api_serve_image)
app.router.add_get('/anomalous/card_cache', media_routes.api_card_cache)
app.router.add_post('/anomalous/card_cache/clear', media_routes.api_clear_card_cache)
app.router.add_post('/anomalous/scan', api_scan_folder)
app.router.add_get('/anomalous/scan_status', api_scan_status)
app.router.add_get('/anomalous/find_model', model_catalog.api_find_model)
app.router.add_get('/anomalous/config', api_get_config)
app.router.add_post('/anomalous/save_config', api_save_config)
app.router.add_post('/anomalous/delete_model', model_metadata.api_delete_model)
app.router.add_post('/anomalous/open_model_folder', model_folder.api_open_model_folder)
app.router.add_get('/anomalous/compatible_models', model_catalog.api_compatible_models)
app.router.add_get('/anomalous/model_guide', model_guide.api_model_guide)
app.router.add_get('/anomalous/notebooks', api_get_notebooks)
app.router.add_get('/anomalous/notebooks/by_node_type', api_get_notebooks_by_node_type)
app.router.add_post('/anomalous/save_notebook', api_save_notebook)
app.router.add_post('/anomalous/delete_notebook', api_delete_notebook)
# Parameter Routes
app.router.add_get('/anomalous/parameters', api_get_parameters)
app.router.add_get('/anomalous/parameters/by_node_type', api_get_parameters_by_type)
app.router.add_get('/anomalous/parameters/signatures', api_get_parameter_set_signatures)
app.router.add_post('/anomalous/save_parameter', api_save_parameter)
app.router.add_post('/anomalous/rename_parameter', api_rename_parameter)
app.router.add_post('/anomalous/delete_parameter', api_delete_parameter)
app.router.add_get('/anomalous/parameter_gallery', api_get_parameter_gallery)
app.router.add_get('/anomalous/parameter_pictures', api_get_parameter_pictures)
# Recipe Routes
app.router.add_get('/anomalous/recipes', recipes.api_get_recipes)
app.router.add_get('/anomalous/example_workflows', example_workflows.api_examples)
app.router.add_get('/anomalous/recipe_full', recipes.api_get_recipe_full)
app.router.add_get('/anomalous/recipe_asset', recipes.api_get_recipe_asset)
app.router.add_get('/anomalous/recipe_gallery', recipes.api_get_recipe_gallery)
app.router.add_get('/anomalous/recipe_parameter_gallery', recipes.api_get_recipe_parameter_gallery)
app.router.add_get('/anomalous/recipe_gallery_compare', recipes.api_get_recipe_gallery_compare)
app.router.add_post('/anomalous/save_recipe', recipes.api_save_recipe)
app.router.add_post('/anomalous/update_recipe', recipes.api_update_recipe)
app.router.add_post('/anomalous/recipe_focus', recipes.api_set_recipe_focus)
app.router.add_post('/anomalous/set_recipe_gallery_cover', recipes.api_set_recipe_gallery_cover)
app.router.add_post('/anomalous/delete_recipe', recipes.api_delete_recipe)
app.router.add_get('/anomalous/recipe_history', recipes.api_get_recipe_history)
app.router.add_get('/anomalous/recipe_version', recipes.api_get_recipe_version)
app.router.add_post('/anomalous/restore_recipe_version', recipes.api_restore_recipe_version)
app.router.add_post('/anomalous/refresh_recipe_identity', recipes.api_refresh_recipe_identity)
app.router.add_post('/anomalous/export_recipe_package', recipe_packages.api_export_recipe_package)
app.router.add_post('/anomalous/import_recipe_package_inspect', recipe_packages.api_import_recipe_package_inspect)
app.router.add_post('/anomalous/import_recipe_package_commit', recipe_packages.api_import_recipe_package_commit)
# Curated Material Library Routes
app.router.add_get('/anomalous/materials', materials.api_get_materials)
app.router.add_get('/anomalous/material_full', materials.api_get_material_full)
app.router.add_get('/anomalous/material_asset', materials.api_get_material_asset)
app.router.add_get('/anomalous/materials/by_node_type', materials.api_get_materials_by_node_type)
app.router.add_post('/anomalous/inspect_image_material', materials.api_inspect_image_material)
app.router.add_post('/anomalous/save_image_material', materials.api_save_image_material)
app.router.add_post('/anomalous/save_prompt_plan', materials.api_save_prompt_plan)
app.router.add_post('/anomalous/save_node_material', node_material.api_save_node_material)
app.router.add_post('/anomalous/delete_material', materials.api_delete_material)
app.router.add_post('/anomalous/update_material', materials.api_update_material)
app.router.add_post('/anomalous/mark_material_moved', materials.api_mark_material_moved)
app.router.add_post('/anomalous/translate', translation_routes.api_translate)
app.router.add_get('/anomalous/base_models', model_catalog.api_base_models)
app.router.add_get('/anomalous/gallery_images', gallery_routes.api_get_gallery_images)
app.router.add_post('/anomalous/delete_gallery_image', gallery_routes.api_delete_gallery_image)
app.router.add_get('/anomalous/output_thumbnail', gallery_routes.api_output_thumbnail)
app.router.add_get('/anomalous/output_preview', gallery_routes.api_output_preview)
app.router.add_get('/anomalous/kept_images', kept_images.api_kept_images)
app.router.add_get('/anomalous/quick_index', quick_index.api_quick_index)
app.router.add_get('/anomalous/resolve_hash', model_resolution.api_resolve_hash)
app.router.add_post('/anomalous/resolve_hash_batch', model_resolution.api_resolve_hash_batch)
app.router.add_get('/anomalous/all_hashes', model_resolution.api_get_all_hashes)
app.router.add_post('/anomalous/scan_all', api_scan_all)
app.router.add_get('/anomalous/global_scan_status', api_global_scan_status)
app.router.add_post('/anomalous/clear_cache', media_routes.api_clear_cache)
app.router.add_post('/anomalous/update_metadata', model_metadata.api_update_metadata)
app.router.add_post('/anomalous/set_custom_cover', model_media.api_set_custom_cover)
app.router.add_post('/anomalous/upload_custom_cover', model_media.api_upload_custom_cover)
app.router.add_get('/anomalous/model_covers', model_media.api_model_covers)
app.router.add_get('/anomalous/model_images', media_routes.api_get_model_images)
app.router.add_post('/anomalous/resolve_paths_to_previews', model_catalog.api_resolve_paths_to_previews)
app.router.add_get('/anomalous/scan_summary', scan_summary.api_scan_summary)
app.router.add_get('/anomalous/scan_matched', scan_summary.api_scan_matched)
app.router.add_get('/anomalous/scan_pickable', scan_summary.api_scan_pickable)
app.router.add_get('/anomalous/last_scan', scan_report.api_last_scan)
app.router.add_get('/anomalous/scan_model', scan_report.api_scan_model)
app.router.add_post('/anomalous/scan_choice', scan_choice.api_set_scan_choice)
app.router.add_get('/anomalous/lora_info', lora_info.api_lora_info)
# Audio & Voice Studio Routes
app.router.add_get('/anomalous/audio_stream', audio_catalog.api_serve_audio)
app.router.add_get('/anomalous/audio_gallery', audio_catalog.api_get_audio_gallery)
app.router.add_post('/anomalous/delete_audio_gallery', audio_catalog.api_delete_audio_gallery)
app.router.add_get('/anomalous/audio_previews', audio_catalog.api_get_audio_previews)
app.router.add_post('/anomalous/save_audio_preview', audio_catalog.api_save_audio_preview)
version_manager.register_routes(app)
tts_version.register_routes(app)
activity_log.register_routes(app)
mcp_server.register_routes(app)
ai_tasks_routes.register_routes(app)
model_download.register_routes(app)
network_check.register_routes(app)
model_usage.register_routes(app)
usage_ledger.register_routes(app)
sidecar_layout.register_routes(app)
model_import.register_routes(app)
model_placement.register_routes(app)
backup.register_routes(app)