fix(editor): an empty Negative prompt box means empty

Studio reads studio_settings.refiner.negative_prompt whenever the wired
negative_prompt is blank. The editor writes the wired one and has no
field for the stored one, so clearing the visible box handed control to
a negative saved in an earlier session, invisibly — a 353-character
negative encoding on a run whose Negative prompt field was empty.

The editor's box now writes both, empty included. The log says which
source supplied the text instead of only how long it was.
This commit is contained in:
digital-garbage
2026-08-23 08:49:09 +03:00
parent 338c6aadc2
commit aea313aefa
4 changed files with 39 additions and 3 deletions
+7
View File
@@ -17,6 +17,13 @@
Phrases are ranked by weight before the cap, and the prompt is located from
`minimax_token_tags` rather than assumed to be the tail of the conditioning.
### Fixed
- **Clearing the editor's Negative prompt box now actually clears it.** Studio falls back to
a negative stored in its own settings whenever the wired one is blank, and the editor has
no field for that stored copy — so emptying the visible box left an earlier negative in
force with nothing on screen saying so. The editor's box is authoritative, empty included.
The log now names which of the two supplied the text.
### Reverted
- **GGUF loading is back to expanding the checkpoint at load.** The quantized path through
ComfyUI-GGUF loaded in seconds instead of a minute, and produced a model the sampler could
+8 -3
View File
@@ -14930,10 +14930,15 @@ class FunPackStudio:
# not evaluated. It still has to be encoded (the output is a real port, and
# negative_erase reads it), but it is a full text-encoder pass and it has to
# be visible when accounting for what a run loaded and when.
# WHICH of the two supplied it. They are different boxes in different
# places, and a stored one silently outranking an empty wired one reads
# as the field on screen having no effect.
source = ("the wired negative_prompt input"
if str(negative_prompt or "").strip()
else "Studio's SAVED setting (the wired negative_prompt input "
"is empty)")
print(f"[FunPackStudio] encoding the negative prompt with the wired CLIP "
f"({len(effective_negative)} chars)"
+ (" — nothing else in this run supplies one"
if negative_conditioning is None else ""))
f"({len(effective_negative)} chars) from {source}")
neg_encoded = clip.encode_from_tokens_scheduled(clip.tokenize(effective_negative))
if neg_encoded:
out_negative = neg_encoded
+5
View File
@@ -505,6 +505,11 @@ def build(object_info: dict, models_config: dict, params: dict, media: dict | No
# (first run after the user clicks "Reset Studio session"); explicit so it's never
# left on from a previous run.
_rf["reset_session"] = bool(params.get("reset_session"))
# The editor's Negative prompt box is the ONLY negative in the editor, so it is
# authoritative — including when it is empty. Studio falls back to this stored
# setting whenever the wired negative is blank, which meant clearing the box left a
# negative from a previous session in force with nothing on screen saying so.
_rf["negative_prompt"] = str(params.get("negative_prompt") or "")
# Project `$name` variables — Studio resolves them dead-last (after split), per scene.
_vars = params.get("variables")
if isinstance(_vars, (list, dict)) and _vars:
+19
View File
@@ -1251,3 +1251,22 @@ def test_two_ACTIVE_sources_on_one_port_are_still_refused():
models = {k: v for k, v in _two_alternatives("none").items() if k != "full_control"}
assert any("already wired from" in e
for e in pipeline_wiring.validate_models_wiring(models))
def test_an_empty_editor_negative_clears_studios_saved_one():
"""Studio falls back to studio_settings.refiner.negative_prompt whenever the wired
negative is blank. The editor has no field for that stored copy, so clearing the visible
Negative prompt box left an old negative in force with nothing on screen saying so."""
import json
graph, _report = builder.build(OI, {"slots": []}, {**PARAMS, "negative_prompt": ""})
settings = json.loads(graph["studio"]["inputs"]["studio_settings"])
assert settings["refiner"]["negative_prompt"] == ""
def test_the_editor_negative_reaches_studios_settings_too():
import json
graph, _report = builder.build(OI, {"slots": []},
{**PARAMS, "negative_prompt": "no hats"})
settings = json.loads(graph["studio"]["inputs"]["studio_settings"])
assert settings["refiner"]["negative_prompt"] == "no hats"
assert graph["neg"]["inputs"]["value"] == "no hats"