feat!: migrate to OpenAI native tool calls and fix circular deps (#fuck-gemini)
- Fix circular dependencies in agent/tools - Migrate from custom JSON to OpenAI tool calls format - Add async streaming (step_stream, complete_stream) - Simplify prompt system and remove token counting - Add 5 new API endpoints (/health, /v1/models, /api/memory/*) - Add 3 new tools (get_torrent_by_index, add_torrent_by_index, set_language) - Fix all 500 tests and add coverage config (80% threshold) - Add comprehensive docs (README, pytest guide) BREAKING: LLM interface changed, memory injection via get_memory()
This commit is contained in:
+30
-28
@@ -1,86 +1,88 @@
|
||||
"""Movie domain entities."""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
|
||||
from ..shared.value_objects import ImdbId, FilePath, FileSize
|
||||
from .value_objects import MovieTitle, ReleaseYear, Quality
|
||||
from ..shared.value_objects import FilePath, FileSize, ImdbId
|
||||
from .value_objects import MovieTitle, Quality, ReleaseYear
|
||||
|
||||
|
||||
@dataclass
|
||||
class Movie:
|
||||
"""
|
||||
Movie entity representing a movie in the media library.
|
||||
|
||||
|
||||
This is the main aggregate root for the movies domain.
|
||||
"""
|
||||
|
||||
imdb_id: ImdbId
|
||||
title: MovieTitle
|
||||
release_year: Optional[ReleaseYear] = None
|
||||
release_year: ReleaseYear | None = None
|
||||
quality: Quality = Quality.UNKNOWN
|
||||
file_path: Optional[FilePath] = None
|
||||
file_size: Optional[FileSize] = None
|
||||
tmdb_id: Optional[int] = None
|
||||
overview: Optional[str] = None
|
||||
poster_path: Optional[str] = None
|
||||
vote_average: Optional[float] = None
|
||||
file_path: FilePath | None = None
|
||||
file_size: FileSize | None = None
|
||||
tmdb_id: int | None = None
|
||||
added_at: datetime = field(default_factory=datetime.now)
|
||||
|
||||
|
||||
def __post_init__(self):
|
||||
"""Validate movie entity."""
|
||||
# Ensure ImdbId is actually an ImdbId instance
|
||||
if not isinstance(self.imdb_id, ImdbId):
|
||||
if isinstance(self.imdb_id, str):
|
||||
object.__setattr__(self, 'imdb_id', ImdbId(self.imdb_id))
|
||||
object.__setattr__(self, "imdb_id", ImdbId(self.imdb_id))
|
||||
else:
|
||||
raise ValueError(f"imdb_id must be ImdbId or str, got {type(self.imdb_id)}")
|
||||
|
||||
raise ValueError(
|
||||
f"imdb_id must be ImdbId or str, got {type(self.imdb_id)}"
|
||||
)
|
||||
|
||||
# Ensure MovieTitle is actually a MovieTitle instance
|
||||
if not isinstance(self.title, MovieTitle):
|
||||
if isinstance(self.title, str):
|
||||
object.__setattr__(self, 'title', MovieTitle(self.title))
|
||||
object.__setattr__(self, "title", MovieTitle(self.title))
|
||||
else:
|
||||
raise ValueError(f"title must be MovieTitle or str, got {type(self.title)}")
|
||||
|
||||
raise ValueError(
|
||||
f"title must be MovieTitle or str, got {type(self.title)}"
|
||||
)
|
||||
|
||||
def has_file(self) -> bool:
|
||||
"""Check if the movie has an associated file."""
|
||||
return self.file_path is not None and self.file_path.exists()
|
||||
|
||||
|
||||
def is_downloaded(self) -> bool:
|
||||
"""Check if the movie is downloaded (has a file)."""
|
||||
return self.has_file()
|
||||
|
||||
|
||||
def get_folder_name(self) -> str:
|
||||
"""
|
||||
Get the folder name for this movie.
|
||||
|
||||
|
||||
Format: "Title (Year)"
|
||||
Example: "Inception (2010)"
|
||||
"""
|
||||
if self.release_year:
|
||||
return f"{self.title.value} ({self.release_year.value})"
|
||||
return self.title.value
|
||||
|
||||
|
||||
def get_filename(self) -> str:
|
||||
"""
|
||||
Get the suggested filename for this movie.
|
||||
|
||||
|
||||
Format: "Title.Year.Quality.ext"
|
||||
Example: "Inception.2010.1080p.mkv"
|
||||
"""
|
||||
parts = [self.title.normalized()]
|
||||
|
||||
|
||||
if self.release_year:
|
||||
parts.append(str(self.release_year.value))
|
||||
|
||||
|
||||
if self.quality != Quality.UNKNOWN:
|
||||
parts.append(self.quality.value)
|
||||
|
||||
|
||||
# Extension will be added based on actual file
|
||||
return ".".join(parts)
|
||||
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.title.value} ({self.release_year.value if self.release_year else 'Unknown'})"
|
||||
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Movie(imdb_id={self.imdb_id}, title='{self.title.value}')"
|
||||
|
||||
Reference in New Issue
Block a user