fix(registry): handle compound subgraph node IDs, add proactive node push from graph hooks

- Handle compound node IDs (e.g. "252:0") from expanded group subgraphs
  to fix 400 Bad Request on workflows with group nodes
- Frontend proactively pushes node data via afterConfigureGraph and
  LiteGraph hooks (onNodeAdded/onNodeRemoved/graphChanged), eliminating
  WebSocket round-trip latency for most "Send to Workflow" operations
- Add content-fingerprint dedup to skip duplicate register-nodes POSTs
- Fast-path cache returns immediately when tabs are registered (including
  0-node registrations), avoiding unnecessary WS refresh cycles
- Distinguish "Empty Registry" from other errors in standalone UI toast
- Reduce WS refresh timeout 2s→0.5s, add cooldown and lock to prevent
  concurrent refresh storms
- All [LM:Registry] logs at DEBUG level
This commit is contained in:
Will Miao
2026-07-13 18:02:26 +08:00
parent 9d85c2a44a
commit 2018722cc8
4 changed files with 228 additions and 35 deletions

View File

@@ -728,6 +728,54 @@ async def test_register_nodes_includes_capabilities():
assert stored_node["widget_names"] == ["ckpt_name"]
@pytest.mark.asyncio
async def test_register_nodes_accepts_compound_node_ids():
"""Subgraph nodes from expanded group nodes have compound IDs like '252:0'."""
node_registry = NodeRegistry()
handler = NodeRegistryHandler(
node_registry=node_registry,
prompt_server=FakePromptServer,
standalone_mode=False,
)
request = FakeRequest(
json_data={
"nodes": [
{
"node_id": "252:0",
"graph_id": "252",
"type": "CheckpointLoaderSimple",
"title": "Checkpoint Loader (subgraph)",
},
{
"node_id": "252:1",
"graph_id": "252",
"type": "CLIPLoader",
"title": "CLIP Loader (subgraph)",
},
],
"client_id": "test-client-1",
}
)
response = await handler.register_nodes(request)
payload = json.loads(response.text)
assert response.status == 200
assert payload["success"] is True
assert "2 nodes registered" in payload["message"]
registry = await node_registry.get_merged_registry()
assert registry["node_count"] == 2
nodes_map = registry["nodes"]
assert "252:0" in nodes_map
assert "252:1" in nodes_map
assert nodes_map["252:0"]["id"] == 0
assert nodes_map["252:0"]["graph_id"] == "252"
assert nodes_map["252:1"]["id"] == 1
@pytest.mark.asyncio
async def test_update_node_widget_sends_payload():
send_calls: list[tuple[str, dict]] = []