fix(agent): clear resumed stream wait status without synthetic reasoning
This commit is contained in:
@@ -21,6 +21,7 @@ class StreamingWaitMonitor:
|
||||
m.last_load_poll = now
|
||||
_load_notice = _managed_local_load_notice(self.agent, self.api_kwargs)
|
||||
if _load_notice is not None:
|
||||
m.wait_notice_started_ts = None # The local loader now owns the display.
|
||||
self.agent._emit_wait_notice(_load_notice)
|
||||
self.agent._touch_activity("local model loading")
|
||||
m.load_notice_shown, m.load_notice_misses, m.last_heartbeat = True, 0, now # loading IS liveness
|
||||
@@ -40,8 +41,9 @@ class StreamingWaitMonitor:
|
||||
# No chunks for 30s+: say WHAT the wait is and WHEN recovery kicks in.
|
||||
stale = self._stream_stale_timeout
|
||||
_recovery = f"; auto-reconnect at {int(stale)}s" if stale is not None and stale != float("inf") else ""
|
||||
self._mon.wait_notice_started_ts = self._mon.last_heartbeat
|
||||
self.agent._emit_wait_notice(
|
||||
f"⏳ waiting on {self.api_kwargs.get('model', 'the provider')} — {waiting_secs}s with no output yet "
|
||||
f"⏳ waiting on {self.api_kwargs.get('model', 'the provider')} — no stream output for {waiting_secs}s "
|
||||
f"(provider may be slow or overloaded, or the model is thinking{_recovery})")
|
||||
else:
|
||||
# Chunks are flowing — keep the tracker fresh, leave the display alone.
|
||||
@@ -49,18 +51,28 @@ class StreamingWaitMonitor:
|
||||
|
||||
def _monitor_loop(self) -> None:
|
||||
_HEARTBEAT_INTERVAL = 30.0 # seconds between gateway activity touches
|
||||
self._mon = SimpleNamespace(last_heartbeat=time.time(), last_load_poll=0.0, load_notice_shown=False, load_notice_misses=0)
|
||||
self._mon = SimpleNamespace(
|
||||
last_heartbeat=time.time(), last_load_poll=0.0,
|
||||
load_notice_shown=False, load_notice_misses=0, wait_notice_started_ts=None,
|
||||
)
|
||||
_is_local_base = bool(self.agent.base_url) and is_local_endpoint(self.agent.base_url)
|
||||
while not self._call_done.is_set():
|
||||
self._call_done.wait(timeout=0.3)
|
||||
_hb_now = time.time()
|
||||
if _is_local_base and self._poll_local_load_notice(_hb_now):
|
||||
continue
|
||||
# Reasoning callbacks do not clear the classic CLI spinner. The empty
|
||||
# protocol payload resets status without adding synthetic reasoning.
|
||||
if (self._mon.wait_notice_started_ts is not None
|
||||
and self.last_chunk_time["t"] > self._mon.wait_notice_started_ts):
|
||||
self.agent._emit_wait_notice("")
|
||||
self._mon.wait_notice_started_ts = None
|
||||
if _hb_now - self._mon.last_heartbeat >= _HEARTBEAT_INTERVAL:
|
||||
self._mon.last_heartbeat = _hb_now
|
||||
self._heartbeat(int(_hb_now - self.last_chunk_time["t"]), _HEARTBEAT_INTERVAL)
|
||||
_stale_elapsed = time.time() - self.last_chunk_time["t"]
|
||||
if _stale_elapsed > self._stream_stale_timeout:
|
||||
self._mon.wait_notice_started_ts = None # Reconnect status has its own owner.
|
||||
self._kill_stale_stream(_stale_elapsed)
|
||||
if self.agent._interrupt_requested:
|
||||
self._abort_for_interrupt(_stale_elapsed)
|
||||
|
||||
Reference in New Issue
Block a user