feat: text gate protected mode — standalone text node (backend)
protected=True makes run() emit stored_text and ignore upstream with no pause; IS_CHANGED caches on stored_text when protected (NaN otherwise). text input is now optional so the node can run standalone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+18
-7
@@ -22,26 +22,37 @@ class TextGate:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
|
# `text` is optional so the node can run standalone in protected mode.
|
||||||
|
# `protected` + `stored_text` are serializing widgets carrying the
|
||||||
|
# authored text-node state (stored_text is hidden by the frontend).
|
||||||
return {
|
return {
|
||||||
"required": {
|
|
||||||
"text": ("STRING", {"forceInput": True}),
|
|
||||||
},
|
|
||||||
"optional": {
|
"optional": {
|
||||||
|
"text": ("STRING", {"forceInput": True}),
|
||||||
"signal": (ANY, {}),
|
"signal": (ANY, {}),
|
||||||
|
"protected": ("BOOLEAN", {"default": False}),
|
||||||
|
"stored_text": ("STRING", {"default": "", "multiline": True}),
|
||||||
},
|
},
|
||||||
"hidden": {"unique_id": "UNIQUE_ID"},
|
"hidden": {"unique_id": "UNIQUE_ID"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def IS_CHANGED(cls, **kwargs):
|
def IS_CHANGED(cls, protected=False, stored_text="", **kwargs):
|
||||||
return float("nan")
|
# Protected = plain text node: cache on the authored text so downstream
|
||||||
|
# only re-runs when it changes. Otherwise never cache (always pause).
|
||||||
|
return stored_text if protected else float("nan")
|
||||||
|
|
||||||
|
def run(self, unique_id=None, text=None, signal=None,
|
||||||
|
protected=False, stored_text=""):
|
||||||
|
if protected:
|
||||||
|
# Standalone text node: emit the authored text, ignore upstream, no
|
||||||
|
# pause. Returns before importing comfy, so it stays import-safe.
|
||||||
|
return (stored_text, signal)
|
||||||
|
|
||||||
def run(self, text, unique_id, signal=None):
|
|
||||||
from . import gate_server
|
from . import gate_server
|
||||||
import comfy.model_management as mm
|
import comfy.model_management as mm
|
||||||
|
|
||||||
gate_bus.GateBus.arm(unique_id)
|
gate_bus.GateBus.arm(unique_id)
|
||||||
gate_server.send_text(unique_id, text)
|
gate_server.send_text(unique_id, text or "")
|
||||||
try:
|
try:
|
||||||
edited = gate_bus.GateBus.wait_payload(
|
edited = gate_bus.GateBus.wait_payload(
|
||||||
unique_id, should_cancel=mm.processing_interrupted)
|
unique_id, should_cancel=mm.processing_interrupted)
|
||||||
|
|||||||
@@ -16,3 +16,31 @@ def test_textgate_io_shape():
|
|||||||
def test_textgate_is_changed_nan():
|
def test_textgate_is_changed_nan():
|
||||||
v = textgate.TextGate.IS_CHANGED(text="hi", unique_id="1")
|
v = textgate.TextGate.IS_CHANGED(text="hi", unique_id="1")
|
||||||
assert math.isnan(v)
|
assert math.isnan(v)
|
||||||
|
|
||||||
|
|
||||||
|
def test_textgate_text_input_is_optional():
|
||||||
|
it = textgate.TextGate.INPUT_TYPES()
|
||||||
|
assert "text" in it["optional"]
|
||||||
|
assert "protected" in it["optional"]
|
||||||
|
assert "stored_text" in it["optional"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_textgate_protected_returns_stored_text_without_pause():
|
||||||
|
# protected mode must return the stored text directly — no GateBus, no comfy
|
||||||
|
out = textgate.TextGate().run(
|
||||||
|
unique_id="1", text="from upstream", signal="sig",
|
||||||
|
protected=True, stored_text="my authored text",
|
||||||
|
)
|
||||||
|
assert out == ("my authored text", "sig")
|
||||||
|
|
||||||
|
|
||||||
|
def test_textgate_is_changed_protected_returns_stored_text():
|
||||||
|
v = textgate.TextGate.IS_CHANGED(
|
||||||
|
unique_id="1", protected=True, stored_text="frozen")
|
||||||
|
assert v == "frozen"
|
||||||
|
|
||||||
|
|
||||||
|
def test_textgate_is_changed_not_protected_is_nan():
|
||||||
|
v = textgate.TextGate.IS_CHANGED(
|
||||||
|
unique_id="1", protected=False, stored_text="ignored")
|
||||||
|
assert math.isnan(v)
|
||||||
|
|||||||
Reference in New Issue
Block a user