fix: Branch button missing on new messages in live chat

The core renderers (drawProcessStep, drawMessageUser, setupCollapsible) clear action button containers with textContent = "" on every update cycle. The previous implementation used a data-branch-injected marker attribute to skip already-patched bars — but since the attribute persists while the button element is removed, re-injection was permanently blocked. Fixed by replacing the marker attribute check with a direct DOM presence check: bar.querySelector(".action-fork_right"). The button is now re-injected whenever the renderer removes it.

keyboardstaff committed Feb 25, 2026 at 00:49 UTC e428f5b384c52ec379798a4526c05141ee404cb9
1 file changed +5 -4
plugins/chat_branching/extensions/webui/set_messages_after_loop/inject-branch-buttons.js
+5 -4
@@ -4,7 +4,6 @@
4 import { createActionButton } from "/components/messages/action-buttons/simple-action-buttons.js";
5 import { callJsonApi } from "/js/api.js";
6
7 -const BRANCH_ATTR = "data-branch-injected";
7 const LOG_NO_ATTR = "data-log-no";
8
9 /**
@@ -24,10 +23,12 @@ export default async function injectBranchButtons(context) {
23 if (el) el.setAttribute(LOG_NO_ATTR, String(msg.no));
24 }
25
27 - // 2. Find every action-button bar that hasn't been patched yet and append a branch btn.
28 - const bars = document.querySelectorAll(`.step-action-buttons:not([${BRANCH_ATTR}])`);
26 + // 2. Inject branch button into every action bar.
27 + // Core renderers clear and rebuild action-button children on each update,
28 + // so we check for the actual button element instead of a marker attribute.
29 + const bars = document.querySelectorAll(".step-action-buttons");
30 for (const bar of bars) {
30 - bar.setAttribute(BRANCH_ATTR, "1");
31 + if (bar.querySelector(".action-fork_right")) continue;
32
33 // Resolve the log no from the nearest stamped ancestor
34 const stamped = bar.closest(`[${LOG_NO_ATTR}]`);