Compare commits
2 Commits
fe95a9af3a
...
0ace20a1bc
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ace20a1bc | |||
| b90d1befe6 |
@@ -23,22 +23,27 @@ The node currently has no explicit state. Add three:
|
|||||||
**Run from here** click → `app.queuePrompt(0, 1)` with `app.queuePrompt(0)`
|
**Run from here** click → `app.queuePrompt(0, 1)` with `app.queuePrompt(0)`
|
||||||
fallback — copied verbatim from the Image Gate's `queueFromHere`.
|
fallback — copied verbatim from the Image Gate's `queueFromHere`.
|
||||||
|
|
||||||
## Sticky edited text
|
## Sticky edited text (by intent, not text comparison)
|
||||||
|
|
||||||
The Image Gate keeps its mask sticky; the Text Gate keeps its text. The live
|
The Image Gate keeps its mask sticky; the Text Gate keeps its text. Stickiness is
|
||||||
textarea IS the sticky store, gated by the last-seen input:
|
keyed off **which action triggered the run**, not a text comparison — because the
|
||||||
|
upstream feeding `text` is often non-deterministic (random/seeded prompts), so a
|
||||||
|
text comparison would wrongly clobber the edit on every Run-from-here.
|
||||||
|
|
||||||
- Track `node._tgInput` = the last incoming text the server pushed.
|
- The "Run from here" button sets `node._tgKeepEdit = true` before re-queuing.
|
||||||
- On each re-pause with `incoming`:
|
- On the next re-pause (`datasete-textgate-show`):
|
||||||
- if `incoming === node._tgInput` (upstream unchanged — the Run-from-here
|
- if `node._tgKeepEdit` → **keep** the current textarea value and clear the
|
||||||
case) → **keep** the current textarea value, so the gate re-runs *your*
|
flag, so the gate re-emits *your* edited text downstream.
|
||||||
edited version (including any edits made after Pass).
|
- else (a normal toolbar Queue) → overwrite the textarea with the incoming
|
||||||
- else (a genuine upstream recompute) → overwrite the textarea with `incoming`.
|
upstream text.
|
||||||
- always set `node._tgInput = incoming`.
|
|
||||||
|
|
||||||
Net: "Run from here" re-runs your version, but a real upstream change still
|
Net: Run-from-here always preserves your edit; a deliberate full Queue shows the
|
||||||
surfaces instead of hiding behind a stale edit. `_tgInput` is per-session
|
fresh upstream text. `_tgKeepEdit` is per-session (not serialized).
|
||||||
(not serialized) — a page reload starts fresh, which is fine.
|
|
||||||
|
**Out of scope:** re-queuing still recomputes non-cacheable upstream nodes — that
|
||||||
|
is inherent to ComfyUI and identical for the Image Gate. With intent-based
|
||||||
|
stickiness the regenerated text is simply ignored, so it can't change the result;
|
||||||
|
to skip the compute, Bypass (Ctrl+B) the upstream node manually.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|||||||
+18
-11
@@ -8,10 +8,13 @@ import { api } from "../../scripts/api.js";
|
|||||||
// edited text back. Outputs are static (text, signal) — no dynamic slots.
|
// edited text back. Outputs are static (text, signal) — no dynamic slots.
|
||||||
//
|
//
|
||||||
// After Pass, a "▶ Run from here" button re-queues the prompt (Image Gate
|
// After Pass, a "▶ Run from here" button re-queues the prompt (Image Gate
|
||||||
// parity): the gate re-arms every run and IS_CHANGED is NaN, so cached upstream
|
// parity): the gate re-arms every run and IS_CHANGED is NaN, so it re-pauses
|
||||||
// means it re-pauses near-instantly. The edited text is sticky — kept across
|
// each run. The edited text is sticky by INTENT: a Run-from-here re-queue keeps
|
||||||
// re-runs while the upstream input is unchanged, so Run-from-here re-runs YOUR
|
// YOUR edited text (even if a non-deterministic upstream regenerates it), while
|
||||||
// version; a genuine upstream change still surfaces the new input.
|
// a normal toolbar Queue shows whatever the upstream produced. Keying off which
|
||||||
|
// button ran — not a text comparison — means a random/seeded upstream can't
|
||||||
|
// clobber the edit on re-run. (Re-queuing still recomputes non-cacheable
|
||||||
|
// upstream, as in any ComfyUI run; that regenerated text is simply ignored.)
|
||||||
//
|
//
|
||||||
// Sizing follows the Image Pool node: the editor is always present and FILLS the
|
// Sizing follows the Image Pool node: the editor is always present and FILLS the
|
||||||
// node, with only a min-height floor (no max) so the node stays freely resizable
|
// node, with only a min-height floor (no max) so the node stays freely resizable
|
||||||
@@ -129,6 +132,7 @@ function setupTextGateNode(node) {
|
|||||||
runHere.textContent = "▶ Run from here";
|
runHere.textContent = "▶ Run from here";
|
||||||
runHere.style.display = "none";
|
runHere.style.display = "none";
|
||||||
runHere.onclick = async () => {
|
runHere.onclick = async () => {
|
||||||
|
node._tgKeepEdit = true; // tell the next re-pause to preserve this edit
|
||||||
node._tg.status.textContent = "re-running…";
|
node._tg.status.textContent = "re-running…";
|
||||||
await queueFromHere(node);
|
await queueFromHere(node);
|
||||||
};
|
};
|
||||||
@@ -173,13 +177,16 @@ app.registerExtension({
|
|||||||
const d = e.detail || {};
|
const d = e.detail || {};
|
||||||
const node = app.graph?.getNodeById?.(parseInt(d.id, 10));
|
const node = app.graph?.getNodeById?.(parseInt(d.id, 10));
|
||||||
if (!node || node.type !== NODE || !node._tg) return;
|
if (!node || node.type !== NODE || !node._tg) return;
|
||||||
const incoming = d.text || "";
|
// Sticky edit by intent: a Run-from-here re-queue (the _tgKeepEdit flag)
|
||||||
// Sticky edit: keep the current editor text when the upstream input is
|
// keeps YOUR edited text so the gate re-emits it downstream; a normal
|
||||||
// unchanged (the Run-from-here case, upstream cached), so the gate re-runs
|
// Queue shows whatever the upstream produced. Keying off the button —
|
||||||
// YOUR version. Only overwrite on a genuine upstream change.
|
// not a text comparison — means a non-deterministic upstream can't
|
||||||
const unchanged = node._tgInput !== undefined && incoming === node._tgInput;
|
// clobber the edit on re-run.
|
||||||
if (!unchanged) node._tg.area.value = incoming;
|
if (node._tgKeepEdit) {
|
||||||
node._tgInput = incoming;
|
node._tgKeepEdit = false;
|
||||||
|
} else {
|
||||||
|
node._tg.area.value = d.text || "";
|
||||||
|
}
|
||||||
setState(node, "paused");
|
setState(node, "paused");
|
||||||
try { node._tg.area.focus(); } catch (err) { /* ignore */ }
|
try { node._tg.area.focus(); } catch (err) { /* ignore */ }
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user