[FIX] Hide ProgressBar when ingest finishes - #132
Conversation
Closes #131 - ready/success branch: reset current+total to 0 so ProgressBar disappears - init branch: also reset current+total to 0 to prevent leaking progress from a previous ingest run
There was a problem hiding this comment.
5 issues found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/four-opencode-brain.ts">
<violation number="1" location="src/four-opencode-brain.ts:694">
P2: Global status channel is overwritten per latest chat message, so concurrent sessions can receive each other’s status updates. This causes incorrect progress/status display across sessions.</violation>
</file>
<file name="src/status.ts">
<violation number="1" location="src/status.ts:54">
P2: getBus permanently caches a rejected BusClient connection. One transient connect failure disables all future bus publishes until process restart.</violation>
</file>
<file name="src/tui.tsx">
<violation number="1" location="src/tui.tsx:80">
P2: Async bus subscription can leak when component unmounts before `BusTui.connect()` resolves. Guard with a disposed flag and close/unsubscribe immediately in the resolve path when already unmounted.</violation>
<violation number="2" location="src/tui.tsx:154">
P2: ProgressBar can remain visible on error/idle because render guard ignores `busy()`. Gate the bar by `busy()` (or clear progress on error) to avoid stale progress display.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
| output.system.push(brainSystemPrompt()); | ||
| }, | ||
| "chat.message": async (_hookInput, output) => { | ||
| if (_hookInput?.sessionID) setSessionId(_hookInput.sessionID); |
There was a problem hiding this comment.
P2: Global status channel is overwritten per latest chat message, so concurrent sessions can receive each other’s status updates. This causes incorrect progress/status display across sessions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/four-opencode-brain.ts, line 694:
<comment>Global status channel is overwritten per latest chat message, so concurrent sessions can receive each other’s status updates. This causes incorrect progress/status display across sessions.</comment>
<file context>
@@ -691,6 +691,7 @@ const _serverPlugin = async (input: PluginInput) => {
output.system.push(brainSystemPrompt());
},
"chat.message": async (_hookInput, output) => {
+ if (_hookInput?.sessionID) setSessionId(_hookInput.sessionID);
if (output.message?.role === "user" && output.message?.content) {
const stored = await onChatMessage(input, output.message as { role: string; content: string });
</file context>
| _busPromise = BusClient.connect().catch((err) => { | ||
| console.warn("[brain] BusClient connect failed:", (err as Error).message); | ||
| throw err; | ||
| }); |
There was a problem hiding this comment.
P2: getBus permanently caches a rejected BusClient connection. One transient connect failure disables all future bus publishes until process restart.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/status.ts, line 54:
<comment>getBus permanently caches a rejected BusClient connection. One transient connect failure disables all future bus publishes until process restart.</comment>
<file context>
@@ -23,22 +24,41 @@ export interface StatusOpts {
+function getBus(): Promise<BusClient> {
+ if (!_busPromise) {
+ _busPromise = BusClient.connect().catch((err) => {
+ console.warn("[brain] BusClient connect failed:", (err as Error).message);
+ throw err;
</file context>
| _busPromise = BusClient.connect().catch((err) => { | |
| console.warn("[brain] BusClient connect failed:", (err as Error).message); | |
| throw err; | |
| }); | |
| _busPromise = BusClient.connect().catch((err) => { | |
| _busPromise = null; | |
| console.warn("[brain] BusClient connect failed:", (err as Error).message); | |
| throw err; | |
| }); |
| }); | ||
|
|
||
| // Real-time WebSocket subscription via plugin bus | ||
| BusTui.connect() |
There was a problem hiding this comment.
P2: Async bus subscription can leak when component unmounts before BusTui.connect() resolves. Guard with a disposed flag and close/unsubscribe immediately in the resolve path when already unmounted.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tui.tsx, line 80:
<comment>Async bus subscription can leak when component unmounts before `BusTui.connect()` resolves. Guard with a disposed flag and close/unsubscribe immediately in the resolve path when already unmounted.</comment>
<file context>
@@ -60,9 +66,30 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi }) {
+ });
+
+ // Real-time WebSocket subscription via plugin bus
+ BusTui.connect()
+ .then((b) => {
+ bus = b;
</file context>
| {busy() ? <Spinner fg={fg()} /> : <text fg={connecting() ? theme().error : fg()}>{indicator()}</text>} | ||
| <text fg={connecting() ? theme().error : theme().textMuted}> {connecting() ? "connecting..." : status()}</text> | ||
| </box> | ||
| {current() > 0 && total() > 0 && ( |
There was a problem hiding this comment.
P2: ProgressBar can remain visible on error/idle because render guard ignores busy(). Gate the bar by busy() (or clear progress on error) to avoid stale progress display.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tui.tsx, line 154:
<comment>ProgressBar can remain visible on error/idle because render guard ignores `busy()`. Gate the bar by `busy()` (or clear progress on error) to avoid stale progress display.</comment>
<file context>
@@ -125,6 +151,9 @@ function BrainStatusBar(props: { centered?: boolean; api: TuiPluginApi }) {
{busy() ? <Spinner fg={fg()} /> : <text fg={connecting() ? theme().error : fg()}>{indicator()}</text>}
<text fg={connecting() ? theme().error : theme().textMuted}> {connecting() ? "connecting..." : status()}</text>
</box>
+ {current() > 0 && total() > 0 && (
+ <ProgressBar current={current()} total={total()} />
+ )}
</file context>
| {current() > 0 && total() > 0 && ( | |
| {busy() && current() > 0 && total() > 0 && ( |
Summary
Resets the
currentandtotalsignals inhandleStatuswhen an ingest finishes (ready/success) and when a new ingest starts (init), so theProgressBarreliably disappears and starts from a clean baseline.Root cause
The render condition in
src/tui.tsxwas:After a busy → ready transition,
busyflipped tofalsebutcurrent/totalretained the last values. On the very next event, thecurrent > 0 && total > 0guard could still evaluatetruebefore any newbusyevent arrived (e.g. during a transient bus reconnect), causing a stale bar to flash. Theinitbranch also didn't reset, so a second ingest could briefly show numbers from a prior run.Changes
src/tui.tsx—handleStatus():initbranch: addsetCurrent(0); setTotal(0);ready/success (else) branch: addsetCurrent(0); setTotal(0);busybranch: unchanged — keeps the live valuesAcceptance
ready(signals zeroed)init→busy) starts from 0/0 (no leaked values)bun run buildsucceeds (server + TUI)current > 0 && total > 0guard is now sufficientCloses #131
Summary by cubic
Hide the ingest
ProgressBaras soon as a run finishes and show it inline only while work is active, now with a light grey bar and black text for better contrast. Status updates stream in real time on session-scoped bus channels with an HTTP fallback, and ingest has a 10s per-file timeout to avoid hangs.Bug Fixes
current/totaloninitand on ready/success so the bar disappears and new ingests start at 0.ProgressBarwith its label to remove the extra line and stop transient flashes; remove the duplicate file counter from busy text.New Features
BusClientonbrain/{sessionId}; TUI subscribes withBusTuiand falls back to HTTP polling.@four-bytes/opencode-plugin-libtov0.5.0and use its sharedProgressBarwith a light grey fill.Written for commit a6bae9b. Summary will update on new commits.