de02bdea06
- Refactor memory system (episodic/STM/LTM with components) - Implement complete subtitle domain (scanner, matcher, placer) - Add YAML workflow infrastructure - Externalize knowledge base (patterns, release groups) - Add comprehensive testing suite - Create manual testing CLIs"
57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
"""Downloads — active torrent downloads being tracked."""
|
|
|
|
import logging
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclass
|
|
class Downloads:
|
|
active: list[dict] = field(default_factory=list)
|
|
|
|
def add(self, download: dict) -> None:
|
|
download["started_at"] = datetime.now().isoformat()
|
|
self.active.append(download)
|
|
logger.info(f"Downloads: Added '{download.get('name')}'")
|
|
|
|
def update_progress(self, task_id: str, progress: int, status: str = "downloading") -> None:
|
|
for dl in self.active:
|
|
if dl.get("task_id") == task_id:
|
|
dl["progress"] = progress
|
|
dl["status"] = status
|
|
dl["updated_at"] = datetime.now().isoformat()
|
|
break
|
|
|
|
def complete(self, task_id: str, file_path: str) -> dict | None:
|
|
for i, dl in enumerate(self.active):
|
|
if dl.get("task_id") == task_id:
|
|
completed = self.active.pop(i)
|
|
completed.update({"status": "completed", "file_path": file_path, "completed_at": datetime.now().isoformat()})
|
|
logger.info(f"Downloads: Completed '{completed.get('name')}'")
|
|
return completed
|
|
return None
|
|
|
|
def clear(self) -> None:
|
|
self.active = []
|
|
|
|
@classmethod
|
|
def describe(cls) -> dict:
|
|
return {
|
|
"name": "Downloads",
|
|
"tier": "episodic",
|
|
"access": "read-write",
|
|
"description": (
|
|
"Active torrent downloads currently in progress. "
|
|
"Read to report download status to the user. "
|
|
"Write to track new downloads or update progress."
|
|
),
|
|
"fields": {
|
|
"active": "List of active downloads. Each entry has task_id, name, progress, status, started_at.",
|
|
},
|
|
}
|
|
|
|
def to_dict(self) -> list:
|
|
return self.active
|