- shader_noise_ksampler: import torch.nn.functional at module level. It was only imported inside one video branch, so the image-side shape correction raised NameError and silently fell back to all-zero shader noise. - shader_noise_ksampler: delete the Parameter Response Mapper block. It referenced an undefined name (the class lives in direct_shader_ksampler), and its trigger input is a V1 `hidden` tuple input, which ComfyUI never delivers, so the block could only ever have raised. - api_routes: keep only known keys before persisting, since the file is read back into shader params on every run; stop returning exception text to the caller; log through the logging module. - gitignore the runtime data/ directory and local console dumps. Behaviour is unchanged: all 11 legacy golden recordings still match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
"""
|
|
API routes for ShaderNoiseKSampler extension.
|
|
|
|
Provides server-side endpoints for saving shader parameters from the frontend.
|
|
"""
|
|
|
|
from aiohttp import web
|
|
import json
|
|
import logging
|
|
import os
|
|
from .shader_params_reader import ShaderParamsReader
|
|
|
|
logger = logging.getLogger("ShaderNoiseKSampler")
|
|
|
|
# Get extension directory
|
|
EXTENSION_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
# Keys the save button sends. Anything else is dropped rather than persisted:
|
|
# the file is read back into shader params on every run, so unknown keys would
|
|
# flow into noise generation untouched by validate_and_sanitize_params.
|
|
ALLOWED_KEYS = frozenset({
|
|
"shaderType",
|
|
"shaderScale",
|
|
"shaderOctaves",
|
|
"shaderWarpStrength",
|
|
"shaderShapeType",
|
|
"shaderShapeStrength",
|
|
"shaderPhaseShift",
|
|
"colorScheme",
|
|
"shaderColorIntensity",
|
|
"visualization_type",
|
|
})
|
|
|
|
|
|
async def save_shader_params(request):
|
|
"""
|
|
API endpoint to save shader parameters to JSON file.
|
|
|
|
Receives JSON data from the frontend and writes it to data/shader_params.json.
|
|
This enables automatic parameter persistence without manual file downloads.
|
|
"""
|
|
try:
|
|
data = await request.json()
|
|
if not isinstance(data, dict):
|
|
return web.json_response(
|
|
{"status": "error", "message": "Expected a JSON object"}, status=400
|
|
)
|
|
|
|
params_file = os.path.join(EXTENSION_DIR, "data", "shader_params.json")
|
|
|
|
# Ensure data directory exists
|
|
os.makedirs(os.path.dirname(params_file), exist_ok=True)
|
|
|
|
# Keep only known keys, then validate and sanitize what is left
|
|
known = {key: value for key, value in data.items() if key in ALLOWED_KEYS}
|
|
sanitized_data = ShaderParamsReader.validate_and_sanitize_params(known)
|
|
|
|
with open(params_file, 'w') as f:
|
|
json.dump(sanitized_data, f, indent=2)
|
|
|
|
logger.info("Saved shader params to %s", params_file)
|
|
return web.json_response({"status": "success"})
|
|
except json.JSONDecodeError:
|
|
return web.json_response({"status": "error", "message": "Invalid JSON"}, status=400)
|
|
except Exception:
|
|
# Log the detail, but do not hand internals back to the caller
|
|
logger.exception("Error saving shader params")
|
|
return web.json_response({"status": "error", "message": "Could not save parameters"}, status=500)
|
|
|
|
|
|
def setup_routes(server):
|
|
"""
|
|
Register API routes with ComfyUI's PromptServer.
|
|
|
|
Args:
|
|
server: The PromptServer instance from ComfyUI
|
|
"""
|
|
if hasattr(server, 'app') and hasattr(server.app, 'router'):
|
|
server.app.router.add_post("/shader_noise_ksampler/save_params", save_shader_params)
|
|
logger.info("Registered API route: POST /shader_noise_ksampler/save_params")
|