From 1ebc74524ada91a1bc503b7faf2bdfb17aa36562 Mon Sep 17 00:00:00 2001 From: 4 Bytes Robby Date: Sun, 14 Jun 2026 12:40:42 +0200 Subject: [PATCH 1/2] fix: use brain/status channel to match server default during ingest #134 --- src/tui.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/tui.tsx b/src/tui.tsx index bd06c26..21dcf91 100644 --- a/src/tui.tsx +++ b/src/tui.tsx @@ -68,6 +68,7 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI onMount(() => { let bus: BusTui | null = null; let unsub: (() => void) | null = null; + let sessionUnsub: (() => void) | null = null; let timer: ReturnType | null = null; let unmounted = false; let busConnected = false; @@ -75,6 +76,7 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI onCleanup(() => { unmounted = true; unsub?.(); + sessionUnsub?.(); bus?.close(); if (timer) clearInterval(timer); }); @@ -86,10 +88,18 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI bus = b; busConnected = true; if (timer) { clearInterval(timer); timer = null; } - const channel = props.sessionId ? `brain/${props.sessionId}` : "brain/status"; - unsub = b.subscribe(channel, (envelope) => { + // Always subscribe to brain/status — server publishes here during ingest, + // before any chat message creates a session. Once sessionId is known, + // also subscribe to the per-session channel (server switches to it + // after first chat.message). Prevents missing pre-session status updates. + unsub = b.subscribe("brain/status", (envelope) => { handleStatus(envelope.payload as BrainStatusEvent); }); + if (props.sessionId) { + sessionUnsub = b.subscribe(`brain/${props.sessionId}`, (envelope) => { + handleStatus(envelope.payload as BrainStatusEvent); + }); + } }) .catch((err) => { console.warn("[brain TUI] BusTui connect failed:", (err as Error).message); From d909ece258af023ccbdf480a372f27e28141e2d1 Mon Sep 17 00:00:00 2001 From: 4 Bytes Robby Date: Sun, 14 Jun 2026 12:50:15 +0200 Subject: [PATCH 2/2] fix: react to late sessionId with createEffect for per-session channel #134 --- src/tui.tsx | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/tui.tsx b/src/tui.tsx index 21dcf91..25fa55b 100644 --- a/src/tui.tsx +++ b/src/tui.tsx @@ -1,6 +1,6 @@ /** @jsxImportSource @opentui/solid */ -import { createSignal, onMount, onCleanup } from "solid-js"; +import { createSignal, createEffect, onMount, onCleanup } from "solid-js"; import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"; import type { RGBA } from "@opentui/core"; import { BusTui } from "@four-bytes/opencode-plugin-lib/tui"; @@ -66,7 +66,8 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI }; onMount(() => { - let bus: BusTui | null = null; + // bus is a signal so createEffect below can react when BusTui resolves. + const [bus, setBus] = createSignal(null); let unsub: (() => void) | null = null; let sessionUnsub: (() => void) | null = null; let timer: ReturnType | null = null; @@ -77,7 +78,7 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI unmounted = true; unsub?.(); sessionUnsub?.(); - bus?.close(); + bus()?.close(); if (timer) clearInterval(timer); }); @@ -85,7 +86,7 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI BusTui.connect() .then((b) => { if (unmounted) { b.close(); return; } - bus = b; + setBus(b); busConnected = true; if (timer) { clearInterval(timer); timer = null; } // Always subscribe to brain/status — server publishes here during ingest, @@ -95,11 +96,6 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI unsub = b.subscribe("brain/status", (envelope) => { handleStatus(envelope.payload as BrainStatusEvent); }); - if (props.sessionId) { - sessionUnsub = b.subscribe(`brain/${props.sessionId}`, (envelope) => { - handleStatus(envelope.payload as BrainStatusEvent); - }); - } }) .catch((err) => { console.warn("[brain TUI] BusTui connect failed:", (err as Error).message); @@ -107,6 +103,19 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi; sessionI if (!timer) timer = setInterval(poll, 200); }); + // React to props.sessionId changes — sessionId is set later by the host + // (after first chat.message), so it is often undefined at mount time. + // Tracks bus() so the effect re-runs once BusTui.connect() resolves. + createEffect(() => { + const sid = props.sessionId; + const b = bus(); + sessionUnsub?.(); + if (!sid || !b) return; + sessionUnsub = b.subscribe(`brain/${sid}`, (envelope) => { + handleStatus(envelope.payload as BrainStatusEvent); + }); + }); + // HTTP fallback for when bus is unavailable (cross-process) let statusUrl = ""; const hash = createHash("md5").update(props.api.state.path.directory).digest("hex").slice(0, 12);