-
Notifications
You must be signed in to change notification settings - Fork 2
fix(tui): "extracting graph..." spinner never cleared after spawn_graph_extraction #1924
Description
Problem
The TUI status bar shows extracting graph... spinner indefinitely after each turn where graph extraction is triggered.
Root cause
In crates/zeph-core/src/agent/persistence.rs:
// line 473
let _ = self.channel.send_status("extracting graph...").await; // spinner ON
// line 489
memory.spawn_graph_extraction(...); // fire-and-forget tokio::spawn — returns immediately
// ← no send_status("") here — spinner is NEVER clearedspawn_graph_extraction() spawns a background task and returns immediately. The status "" is only reset inside check_summarization() (line 527), which is a separate code path. After graph extraction is spawned, the status bar is never cleared.
Additionally, if the extraction LLM times out (extraction_timeout_secs = 15 default), the timeout is silently swallowed with only a tracing::warn — the spinner still stays visible.
Fix options
Option A (simplest): Clear status immediately after spawn_graph_extraction():
memory.spawn_graph_extraction(...);
let _ = self.channel.send_status("").await; // clear right awayThis is honest — the task is background, the UI shouldn't pretend to be waiting for it.
Option B (accurate): Pass a oneshot::Sender into the background task and clear the status when the task completes or times out:
let (done_tx, done_rx) = tokio::sync::oneshot::channel();
memory.spawn_graph_extraction(..., Some(done_tx));
// inside spawn: done_tx.send(()) on completion/error/timeout
// in agent: await done_rx then send_status("")This would require making the agent block on extraction, defeating the fire-and-forget design.
Recommended: Option A. Since extraction is intentionally async and non-blocking, the status message should reflect that — e.g. change the label to "saving to graph..." and clear it immediately after spawn, or simply remove the send_status call entirely for this path.
Affected code
crates/zeph-core/src/agent/persistence.rslines 473–489
Steps to reproduce
- Enable graph memory in config (
[memory.graph] enabled = true) - Start a conversation — after each turn the TUI shows
extracting graph... - The spinner never goes away until the next status event overwrites it