fix(models): stop reporting errored downloads as still downloading (#926)

TaskManager.error_download() intentionally keeps a failed task in the
active list (status="error") so /tasks/active can surface the error
and retry UI — but /models/status derived its "downloading" flag from
the same unfiltered list. One failed download therefore showed the
model as downloading:true / downloaded:false for the life of the
process, masking the model's real cache state (even a fully valid
on-disk cache) until an app restart. Likely behind endless-spinner
reports like #181 and the restart-fixes-it pattern in #883.

Add TaskManager.get_pending_downloads() (downloading/extracting only)
and use it in /models/status; /tasks/active behavior is unchanged.

Fixes #925


Claude-Session: https://claude.ai/code/session_011iwL9AyeAWgz2jpgcHxJpC

Co-authored-by: Claude Fable 5 <[email protected]>
This commit is contained in:
Daniel Knoodle
2026-07-20 12:41:19 -07:00
committed by Jamie Pine
co-authored by Claude Fable 5
parent 7d3f7b96d7
commit f7c08477a0
3 changed files with 68 additions and 1 deletions
+13
View File
@@ -67,6 +67,19 @@ class TaskManager:
def get_active_downloads(self) -> List[DownloadTask]:
"""Get all active downloads."""
return list(self._active_downloads.values())
def get_pending_downloads(self) -> List[DownloadTask]:
"""Get downloads that are still in flight.
Excludes errored tasks, which stay in the active list so the
error/retry UI can show them but must not be reported as
"downloading" by /models/status.
"""
return [
task
for task in self._active_downloads.values()
if task.status in ("downloading", "extracting")
]
def get_active_generations(self) -> List[GenerationTask]:
"""Get all active generations."""