diff --git a/conditioning.py b/conditioning.py index 1eee5553..4a379cb9 100644 --- a/conditioning.py +++ b/conditioning.py @@ -11937,6 +11937,9 @@ class FunPackStudio: else: active_prompt = str(sb.get("scene_positive", "") or "").strip() or str(positive_prompt or "").strip() + # --- Overrides: when True, popup value wins over connected input --- + ov = settings.get("overrides", {}) if isinstance(settings.get("overrides"), dict) else {} + # --- Refiner settings --- rf = settings.get("refiner", {}) if isinstance(settings.get("refiner"), dict) else {} mode = str(rf.get("mode", "Refine") or "Refine") @@ -11945,13 +11948,28 @@ class FunPackStudio: prompt_repair = bool(rf.get("prompt_repair", True)) im_feeling_lucky = bool(rf.get("im_feeling_lucky", False)) reset_session = bool(rf.get("reset_session", False)) - # Connected input takes precedence over popup value - feedback_prompt = str(feedback_prompt) if feedback_prompt is not None else str(rf.get("feedback_prompt", "") or "") - intent_override = str(rf.get("user_intent_prompt_override", "") or "") - effective_intent = intent_override or str(user_intent_prompt or "") - # --- Refinement key --- - key = str(settings.get("refinement_key", "") or "").strip() + # feedback_prompt: popup wins if override is on, else external wins + popup_feedback = str(rf.get("feedback_prompt", "") or "") + if ov.get("feedback_prompt"): + feedback_prompt = popup_feedback + else: + feedback_prompt = str(feedback_prompt) if feedback_prompt is not None else popup_feedback + + # user_intent_prompt: popup wins if override is on, else external wins + popup_intent = str(rf.get("user_intent_prompt_override", "") or "") + if ov.get("user_intent_prompt"): + effective_intent = popup_intent + else: + effective_intent = str(user_intent_prompt or "") or popup_intent + + # --- Refinement key: popup wins if override is on, else external input wins --- + popup_key = str(settings.get("refinement_key", "") or "").strip() + if ov.get("refinement_key"): + key = popup_key + refinement_key_input = "" # suppress external so refine_v2 uses widget key + else: + key = popup_key # refine_v2 uses refinement_key_input when non-empty # --- Advisor LLM --- advisor_clip = None diff --git a/web/funpack_studio.js b/web/funpack_studio.js index 1b82d3a7..0774b89f 100644 --- a/web/funpack_studio.js +++ b/web/funpack_studio.js @@ -59,6 +59,7 @@ function deepMerge(target, src) { function defaultSettings() { return { refinement_key: "", + overrides: { refinement_key: false, feedback_prompt: false, user_intent_prompt: false }, scene_builder: { mode: "Pass-through", scene: NONE_SENTINEL, scene_name: "", aliases: "", scene_positive: "", scene_negative: "" }, refiner: { mode: "Refine", advisor_mode: "Off", advisor_thinking: true, prompt_repair: true, im_feeling_lucky: false, reset_session: false, feedback_prompt: "", user_intent_prompt_override: "" }, advisor_llm: { enabled: false, model_path: "huihui-ai/Huihui-Qwen3-8B-abliterated-v2", dtype: "bfloat16" }, @@ -66,6 +67,14 @@ function defaultSettings() { }; } +function overrideToggle(settings, key, label) { + if (!settings.overrides) settings.overrides = {}; + const { wrap, inp } = toggleEl(settings.overrides[key] || false, label); + inp.addEventListener("change", () => { settings.overrides[key] = inp.checked; }); + wrap.className += " funpack-studio-override-toggle"; + return wrap; +} + function linkedRefinementKey(node) { const input = (node.inputs || []).find((i) => i.name === "refinement_key_input"); const linkId = Array.isArray(input?.link) ? input.link[0] : input?.link; @@ -276,11 +285,13 @@ function openPanel(node) { const linkedKey = linkedRefinementKey(node); if (linkedKey) { - const hint = el("div", "funpack-studio-hint", `Linked key from node input: ${linkedKey} (takes precedence at runtime)`); + const hint = el("div", "funpack-studio-hint", `Linked key from node input: ${linkedKey}`); body.append(hint); } body.append(row("Session key", keyInput)); + body.append(overrideToggle(settings, "refinement_key", + "Override - use popup key even when refinement_key_input is connected")); const resetToggle = toggleEl(settings.refiner.reset_session, "Reset session on next run"); resetToggle.inp.addEventListener("change", () => { settings.refiner.reset_session = resetToggle.inp.checked; }); @@ -446,17 +457,20 @@ function openPanel(node) { body.append(row("Lucky", luckyToggle.wrap)); body.append(sectionTitle("Feedback")); - + body.append(overrideToggle(settings, "feedback_prompt", + "Override - use popup value even when feedback_prompt input is connected")); const fbArea = el("textarea", "funpack-studio-textarea short"); fbArea.value = settings.refiner.feedback_prompt || ""; - fbArea.placeholder = "Optional feedback: describe what was wrong with the previous output..."; + fbArea.placeholder = "Feedback: describe what was wrong with the previous output..."; fbArea.addEventListener("input", () => { settings.refiner.feedback_prompt = fbArea.value; }); body.append(fbArea); - body.append(sectionTitle("Intent override")); + body.append(sectionTitle("Intent")); + body.append(overrideToggle(settings, "user_intent_prompt", + "Override - use popup value even when user_intent_prompt input is connected")); const intentArea = el("textarea", "funpack-studio-textarea short"); intentArea.value = settings.refiner.user_intent_prompt_override || ""; - intentArea.placeholder = "Optional intent override (overrides the user_intent_prompt input)..."; + intentArea.placeholder = "Intent override (overrides the user_intent_prompt node input)..."; intentArea.addEventListener("input", () => { settings.refiner.user_intent_prompt_override = intentArea.value; }); body.append(intentArea); } @@ -803,6 +817,8 @@ function injectStyles() { background: rgba(255,255,255,0.07); color: #eee; cursor: pointer; font: 11px sans-serif; } .funpack-studio-chip:hover { background: rgba(100,210,140,0.25); border-color: rgba(100,210,140,0.5); } + .funpack-studio-override-toggle { color: #9da6b0; font-size: 11px; margin-bottom: 3px; } + .funpack-studio-override-toggle span { color: #9da6b0; } `; document.head.append(style); }