When a KSampler marked as 'Send Gen Params Target' has widget inputs
wired to Primitive nodes (PrimitiveNode, PrimitiveInt, PrimitiveFloat,
etc.), sending gen params from the Lora Manager UI now updates the
Primitive node's value instead of the KSampler widget. This is
necessary because ComfyUI's execution engine reads from the connected
input, ignoring the widget value when a wire is present.
Also fix two minor issues found during review:
- Remove unnecessary String() wrapping on numeric gen params (seed,
steps, cfg) to preserve native types through the JSON/WS path
- Correct misleading isNodeEnabled comment: LGraphEventMode values
are 0=Always, 2=Never, 4=Bypass (not 'Normal/Enabled')
- workflow_registry.js: add force param to refreshRegistry(), bypass fingerprint
dedup when responding to lora_registry_refresh WS message. Without this, the
backend's wait_for_all() times out after 0.5s because the frontend skips the
register-nodes POST when the workflow fingerprint hasn't changed (common after
ComfyUI restart with an empty or unchanged workflow).
- misc_handlers.py: demote 'No nodes registered after refresh' from WARNING to
DEBUG — empty workflows are a normal operational state, not a warning-worthy
condition.
- 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
Move NodeRegistry from a single global _nodes dict to a per-client
(_tab_nodes) structure so that multiple ComfyUI browser tabs no
longer overwrite each other's workflow node data during a
lora_registry_refresh cycle. The merged result is a union of all
known tabs' target nodes, eliminating the non-deterministic failure
where send-to-workflow could randomly target a tab lacking valid
targets.
- NodeRegistry.register_nodes(sid, nodes) replaces per-tab data
without affecting other tabs.
- NodeRegistry.get_merged_registry() returns the union across all
connected clients, together with tab_count / per-tab metadata.
- prepare_for_refresh() snapshots the current active sockets; caller
re-reads before merging so that newly-connected tabs are not pruned.
- workflow_registry.js sends api.clientId in the POST body so the
backend can identify which tab is registering.
- Fix Vue mode: text widgets (CLIPTextEncode, Prompt LM) had no
[data-testid=widget-layout-field-label], so findRowEl never matched.
Added fallback strategies: bare <label> text match and widget index match.
- Fix Vue mode: flash background pulse was never applied — @keyframes was
defined but no rule bound it to .lm-flash. Replaced with CSS transition
on .lm-flash-host class for value text color fade-in/fade-out.
- Fix Vue mode: -webkit-text-fill-color set by ComfyUI overrode
even with !important. Added -webkit-text-fill-color override to .lm-flash.
- Fix canvas mode: highlight rect was double-offset because onDrawForeground
ctx is pre-translated to node.pos. Removed background rect entirely per
design decision; kept text_color + inline color only.
- Add fade-in (250ms) / fade-out (400ms) for text color in both modes.
Canvas-drawn widgets use rAF color interpolation; DOM widgets use CSS
transition. Fixed hexToRgb to handle 3-digit hex shorthand (#DDD).
- Add hover dismissal to canvas mode via app.canvas.getWidgetAtCursor().
Vue mode already had it via mouseover listener.
- Replace 60fps rAF poll with 100ms setInterval for hover detection.
- Fix batch cleanup closure bug: isDomWidget evaluated per-widget instead
of per-call; fade rAF cancellers tracked per-widget in _lmFadeCancels map.
- Unify flash color from #66B3FF to LM brand accent #4299E0.
- Fix Vue fade-out: keep .lm-flash-host 300ms after removing .lm-flash so
CSS transition persists. Canvas DOM widgets: keep inline transition 300ms
after clearing color.
- Fix copy button on embedding cards to copy 'embedding:folder/name' format
- Add send-embedding-to-workflow for Prompt (LoraManager), Text (LoraManager),
and CLIPTextEncode nodes, appending embedding code to text content
- Extend workflow registry to register text-capable nodes by comfyClass
(not generic widget name 'text') to avoid false matches
- Add mode parameter to update_node_widget API/event for append support
- Fix single/bulk context menus: single shows plain 'Send to Workflow',
bulk collapses submenu into direct action for embeddings (append-only)
- Add capabilities parsing and validation for node registration
- Implement widget_names extraction from capabilities with type safety
- Add supports_lora boolean conversion in capabilities
- Include comfy_class fallback to node_type when missing
- Add new update_node_widget API endpoint for bulk widget updates
- Improve error handling and input validation for widget updates
- Remove unused parameters from node selector event setup function
These changes improve node metadata handling and enable dynamic widget management capabilities.