mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-08 15:00:15 -03:00
feat(api): add GET endpoints for update-lora-code and update-node-widget
Add GET variants of the two POST endpoints used by the send-to-workflow feature. Parameters are read from query string instead of JSON body, supporting both simple repeated node_id params and JSON-encoded node_ids for complex graph references.
This commit is contained in:
@@ -1784,6 +1784,124 @@ class LoraCodeHandler:
|
|||||||
logger.error("Failed to update lora code: %s", exc, exc_info=True)
|
logger.error("Failed to update lora code: %s", exc, exc_info=True)
|
||||||
return web.json_response({"success": False, "error": str(exc)}, status=500)
|
return web.json_response({"success": False, "error": str(exc)}, status=500)
|
||||||
|
|
||||||
|
async def get_update_lora_code(self, request: web.Request) -> web.Response:
|
||||||
|
"""GET version of update_lora_code — reads parameters from query string.
|
||||||
|
|
||||||
|
Query params:
|
||||||
|
lora_code (required) — the LoRA syntax to send
|
||||||
|
mode (optional) — "append" (default) or "replace"
|
||||||
|
node_id (repeatable) — target node id(s), e.g. node_id=3&node_id=5
|
||||||
|
node_ids (optional) — JSON-encoded array for complex references with graph_id:
|
||||||
|
[{"node_id":3,"graph_id":"g1"}, ...]
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
node_ids_raw = request.query.get("node_ids")
|
||||||
|
node_id_list = request.query.getall("node_id", [])
|
||||||
|
lora_code = request.query.get("lora_code", "")
|
||||||
|
mode = request.query.get("mode", "append")
|
||||||
|
|
||||||
|
if not lora_code:
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "Missing lora_code parameter"},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
node_ids = None
|
||||||
|
if node_ids_raw:
|
||||||
|
try:
|
||||||
|
node_ids = json.loads(node_ids_raw)
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "node_ids must be a valid JSON array"},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
if not isinstance(node_ids, list) or not node_ids:
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "node_ids must be a non-empty JSON array"},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
elif node_id_list:
|
||||||
|
node_ids = node_id_list
|
||||||
|
|
||||||
|
results = []
|
||||||
|
if node_ids is None:
|
||||||
|
try:
|
||||||
|
self._prompt_server.instance.send_sync(
|
||||||
|
"lora_code_update",
|
||||||
|
{"id": -1, "lora_code": lora_code, "mode": mode},
|
||||||
|
)
|
||||||
|
results.append({"node_id": "broadcast", "success": True})
|
||||||
|
except Exception as exc: # pragma: no cover - defensive logging
|
||||||
|
logger.error("Error broadcasting lora code: %s", exc)
|
||||||
|
results.append(
|
||||||
|
{"node_id": "broadcast", "success": False, "error": str(exc)}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for entry in node_ids:
|
||||||
|
node_identifier = entry
|
||||||
|
graph_identifier = None
|
||||||
|
if isinstance(entry, dict):
|
||||||
|
node_identifier = entry.get("node_id")
|
||||||
|
graph_identifier = entry.get("graph_id")
|
||||||
|
|
||||||
|
if node_identifier is None:
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"node_id": node_identifier,
|
||||||
|
"graph_id": graph_identifier,
|
||||||
|
"success": False,
|
||||||
|
"error": "Missing node_id parameter",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
parsed_node_id = int(node_identifier)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
parsed_node_id = node_identifier
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"id": parsed_node_id,
|
||||||
|
"lora_code": lora_code,
|
||||||
|
"mode": mode,
|
||||||
|
}
|
||||||
|
|
||||||
|
if graph_identifier is not None:
|
||||||
|
payload["graph_id"] = str(graph_identifier)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._prompt_server.instance.send_sync(
|
||||||
|
"lora_code_update",
|
||||||
|
payload,
|
||||||
|
)
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"node_id": parsed_node_id,
|
||||||
|
"graph_id": payload.get("graph_id"),
|
||||||
|
"success": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception as exc: # pragma: no cover - defensive logging
|
||||||
|
logger.error(
|
||||||
|
"Error sending lora code to node %s (graph %s): %s",
|
||||||
|
parsed_node_id,
|
||||||
|
graph_identifier,
|
||||||
|
exc,
|
||||||
|
)
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"node_id": parsed_node_id,
|
||||||
|
"graph_id": payload.get("graph_id"),
|
||||||
|
"success": False,
|
||||||
|
"error": str(exc),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return web.json_response({"success": True, "results": results})
|
||||||
|
except Exception as exc: # pragma: no cover - defensive logging
|
||||||
|
logger.error("Failed to update lora code (GET): %s", exc, exc_info=True)
|
||||||
|
return web.json_response({"success": False, "error": str(exc)}, status=500)
|
||||||
|
|
||||||
|
|
||||||
class TrainedWordsHandler:
|
class TrainedWordsHandler:
|
||||||
async def get_trained_words(self, request: web.Request) -> web.Response:
|
async def get_trained_words(self, request: web.Request) -> web.Response:
|
||||||
@@ -3431,6 +3549,130 @@ class NodeRegistryHandler:
|
|||||||
logger.error("Failed to update node widget: %s", exc, exc_info=True)
|
logger.error("Failed to update node widget: %s", exc, exc_info=True)
|
||||||
return web.json_response({"success": False, "error": str(exc)}, status=500)
|
return web.json_response({"success": False, "error": str(exc)}, status=500)
|
||||||
|
|
||||||
|
async def get_update_node_widget(self, request: web.Request) -> web.Response:
|
||||||
|
"""GET version of update_node_widget — reads parameters from query string.
|
||||||
|
|
||||||
|
Query params:
|
||||||
|
widget_name (optional) — the widget name to update (required unless action is set)
|
||||||
|
action (optional) — alternative action, e.g. "inject_text" (required unless widget_name is set)
|
||||||
|
value (required) — the value to set
|
||||||
|
mode (optional) — "replace" (default) or "append"
|
||||||
|
node_id (repeatable) — target node id(s), e.g. node_id=3&node_id=5
|
||||||
|
node_ids (optional) — JSON-encoded array for complex references:
|
||||||
|
[{"node_id":3,"graph_id":"g1"}, ...]
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
widget_name = request.query.get("widget_name")
|
||||||
|
action = request.query.get("action")
|
||||||
|
value = request.query.get("value")
|
||||||
|
mode = request.query.get("mode", "replace")
|
||||||
|
node_ids_raw = request.query.get("node_ids")
|
||||||
|
node_id_list = request.query.getall("node_id", [])
|
||||||
|
|
||||||
|
if not action and (not isinstance(widget_name, str) or not widget_name):
|
||||||
|
return web.json_response(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"error": "Missing parameter: provide either 'action' or 'widget_name'",
|
||||||
|
},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not isinstance(value, str) or not value:
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "Missing value parameter"}, status=400
|
||||||
|
)
|
||||||
|
|
||||||
|
node_ids = None
|
||||||
|
if node_ids_raw:
|
||||||
|
try:
|
||||||
|
node_ids = json.loads(node_ids_raw)
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "node_ids must be a valid JSON array"},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
if not isinstance(node_ids, list) or not node_ids:
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "node_ids must be a non-empty JSON array"},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
elif node_id_list:
|
||||||
|
node_ids = node_id_list
|
||||||
|
|
||||||
|
if not isinstance(node_ids, list) or not node_ids:
|
||||||
|
return web.json_response(
|
||||||
|
{"success": False, "error": "node_ids must be a non-empty list"},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for entry in node_ids:
|
||||||
|
node_identifier = entry
|
||||||
|
graph_identifier = None
|
||||||
|
if isinstance(entry, dict):
|
||||||
|
node_identifier = entry.get("node_id")
|
||||||
|
graph_identifier = entry.get("graph_id")
|
||||||
|
|
||||||
|
if node_identifier is None:
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"node_id": node_identifier,
|
||||||
|
"graph_id": graph_identifier,
|
||||||
|
"success": False,
|
||||||
|
"error": "Missing node_id parameter",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
parsed_node_id = int(node_identifier)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
parsed_node_id = node_identifier
|
||||||
|
|
||||||
|
payload: dict = {
|
||||||
|
"id": parsed_node_id,
|
||||||
|
"value": value,
|
||||||
|
"mode": mode,
|
||||||
|
}
|
||||||
|
if action:
|
||||||
|
payload["action"] = action
|
||||||
|
if widget_name:
|
||||||
|
payload["widget_name"] = widget_name
|
||||||
|
|
||||||
|
if graph_identifier is not None:
|
||||||
|
payload["graph_id"] = str(graph_identifier)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._prompt_server.instance.send_sync("lm_widget_update", payload)
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"node_id": parsed_node_id,
|
||||||
|
"graph_id": payload.get("graph_id"),
|
||||||
|
"success": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception as exc: # pragma: no cover - defensive logging
|
||||||
|
logger.error(
|
||||||
|
"Error sending widget update to node %s (graph %s): %s",
|
||||||
|
parsed_node_id,
|
||||||
|
graph_identifier,
|
||||||
|
exc,
|
||||||
|
)
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"node_id": parsed_node_id,
|
||||||
|
"graph_id": payload.get("graph_id"),
|
||||||
|
"success": False,
|
||||||
|
"error": str(exc),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return web.json_response({"success": True, "results": results})
|
||||||
|
except Exception as exc: # pragma: no cover - defensive logging
|
||||||
|
logger.error("Failed to update node widget (GET): %s", exc, exc_info=True)
|
||||||
|
return web.json_response({"success": False, "error": str(exc)}, status=500)
|
||||||
|
|
||||||
|
|
||||||
class MiscHandlerSet:
|
class MiscHandlerSet:
|
||||||
"""Aggregate handlers into a lookup compatible with the registrar."""
|
"""Aggregate handlers into a lookup compatible with the registrar."""
|
||||||
@@ -3497,10 +3739,12 @@ class MiscHandlerSet:
|
|||||||
"update_usage_stats": self.usage_stats.update_usage_stats,
|
"update_usage_stats": self.usage_stats.update_usage_stats,
|
||||||
"get_usage_stats": self.usage_stats.get_usage_stats,
|
"get_usage_stats": self.usage_stats.get_usage_stats,
|
||||||
"update_lora_code": self.lora_code.update_lora_code,
|
"update_lora_code": self.lora_code.update_lora_code,
|
||||||
|
"get_update_lora_code": self.lora_code.get_update_lora_code,
|
||||||
"get_trained_words": self.trained_words.get_trained_words,
|
"get_trained_words": self.trained_words.get_trained_words,
|
||||||
"get_model_example_files": self.model_examples.get_model_example_files,
|
"get_model_example_files": self.model_examples.get_model_example_files,
|
||||||
"register_nodes": self.node_registry.register_nodes,
|
"register_nodes": self.node_registry.register_nodes,
|
||||||
"update_node_widget": self.node_registry.update_node_widget,
|
"update_node_widget": self.node_registry.update_node_widget,
|
||||||
|
"get_update_node_widget": self.node_registry.get_update_node_widget,
|
||||||
"get_registry": self.node_registry.get_registry,
|
"get_registry": self.node_registry.get_registry,
|
||||||
"check_model_exists": self.model_library.check_model_exists,
|
"check_model_exists": self.model_library.check_model_exists,
|
||||||
"check_models_exist": self.model_library.check_models_exist,
|
"check_models_exist": self.model_library.check_models_exist,
|
||||||
|
|||||||
@@ -39,10 +39,12 @@ MISC_ROUTE_DEFINITIONS: tuple[RouteDefinition, ...] = (
|
|||||||
RouteDefinition("POST", "/api/lm/update-usage-stats", "update_usage_stats"),
|
RouteDefinition("POST", "/api/lm/update-usage-stats", "update_usage_stats"),
|
||||||
RouteDefinition("GET", "/api/lm/get-usage-stats", "get_usage_stats"),
|
RouteDefinition("GET", "/api/lm/get-usage-stats", "get_usage_stats"),
|
||||||
RouteDefinition("POST", "/api/lm/update-lora-code", "update_lora_code"),
|
RouteDefinition("POST", "/api/lm/update-lora-code", "update_lora_code"),
|
||||||
|
RouteDefinition("GET", "/api/lm/update-lora-code", "get_update_lora_code"),
|
||||||
RouteDefinition("GET", "/api/lm/trained-words", "get_trained_words"),
|
RouteDefinition("GET", "/api/lm/trained-words", "get_trained_words"),
|
||||||
RouteDefinition("GET", "/api/lm/model-example-files", "get_model_example_files"),
|
RouteDefinition("GET", "/api/lm/model-example-files", "get_model_example_files"),
|
||||||
RouteDefinition("POST", "/api/lm/register-nodes", "register_nodes"),
|
RouteDefinition("POST", "/api/lm/register-nodes", "register_nodes"),
|
||||||
RouteDefinition("POST", "/api/lm/update-node-widget", "update_node_widget"),
|
RouteDefinition("POST", "/api/lm/update-node-widget", "update_node_widget"),
|
||||||
|
RouteDefinition("GET", "/api/lm/update-node-widget", "get_update_node_widget"),
|
||||||
RouteDefinition("GET", "/api/lm/get-registry", "get_registry"),
|
RouteDefinition("GET", "/api/lm/get-registry", "get_registry"),
|
||||||
RouteDefinition("GET", "/api/lm/check-model-exists", "check_model_exists"),
|
RouteDefinition("GET", "/api/lm/check-model-exists", "check_model_exists"),
|
||||||
RouteDefinition("GET", "/api/lm/check-models-exist", "check_models_exist"),
|
RouteDefinition("GET", "/api/lm/check-models-exist", "check_models_exist"),
|
||||||
|
|||||||
Reference in New Issue
Block a user