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:
@@ -1,8 +1,8 @@
|
||||
"""Subtitle domain entities."""
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from ..shared.value_objects import ImdbId, FilePath
|
||||
from dataclasses import dataclass
|
||||
|
||||
from ..shared.value_objects import FilePath, ImdbId
|
||||
from .value_objects import Language, SubtitleFormat, TimingOffset
|
||||
|
||||
|
||||
@@ -10,62 +10,65 @@ from .value_objects import Language, SubtitleFormat, TimingOffset
|
||||
class Subtitle:
|
||||
"""
|
||||
Subtitle entity representing a subtitle file.
|
||||
|
||||
|
||||
Can be associated with either a movie or a TV show episode.
|
||||
"""
|
||||
|
||||
media_imdb_id: ImdbId
|
||||
language: Language
|
||||
format: SubtitleFormat
|
||||
file_path: FilePath
|
||||
|
||||
|
||||
# Optional: for TV shows
|
||||
season_number: Optional[int] = None
|
||||
episode_number: Optional[int] = None
|
||||
|
||||
season_number: int | None = None
|
||||
episode_number: int | None = None
|
||||
|
||||
# Subtitle metadata
|
||||
timing_offset: TimingOffset = TimingOffset(0)
|
||||
hearing_impaired: bool = False
|
||||
forced: bool = False # Forced subtitles (for foreign language parts)
|
||||
|
||||
|
||||
# Source information
|
||||
source: Optional[str] = None # e.g., "OpenSubtitles", "Subscene"
|
||||
uploader: Optional[str] = None
|
||||
download_count: Optional[int] = None
|
||||
rating: Optional[float] = None
|
||||
|
||||
source: str | None = None # e.g., "OpenSubtitles", "Subscene"
|
||||
uploader: str | None = None
|
||||
download_count: int | None = None
|
||||
rating: float | None = None
|
||||
|
||||
def __post_init__(self):
|
||||
"""Validate subtitle entity."""
|
||||
# Ensure ImdbId is actually an ImdbId instance
|
||||
if not isinstance(self.media_imdb_id, ImdbId):
|
||||
if isinstance(self.media_imdb_id, str):
|
||||
object.__setattr__(self, 'media_imdb_id', ImdbId(self.media_imdb_id))
|
||||
|
||||
object.__setattr__(self, "media_imdb_id", ImdbId(self.media_imdb_id))
|
||||
|
||||
# Ensure Language is actually a Language instance
|
||||
if not isinstance(self.language, Language):
|
||||
if isinstance(self.language, str):
|
||||
object.__setattr__(self, 'language', Language.from_code(self.language))
|
||||
|
||||
object.__setattr__(self, "language", Language.from_code(self.language))
|
||||
|
||||
# Ensure SubtitleFormat is actually a SubtitleFormat instance
|
||||
if not isinstance(self.format, SubtitleFormat):
|
||||
if isinstance(self.format, str):
|
||||
object.__setattr__(self, 'format', SubtitleFormat.from_extension(self.format))
|
||||
|
||||
object.__setattr__(
|
||||
self, "format", SubtitleFormat.from_extension(self.format)
|
||||
)
|
||||
|
||||
# Ensure FilePath is actually a FilePath instance
|
||||
if not isinstance(self.file_path, FilePath):
|
||||
object.__setattr__(self, 'file_path', FilePath(self.file_path))
|
||||
|
||||
object.__setattr__(self, "file_path", FilePath(self.file_path))
|
||||
|
||||
def is_for_movie(self) -> bool:
|
||||
"""Check if this subtitle is for a movie."""
|
||||
return self.season_number is None and self.episode_number is None
|
||||
|
||||
|
||||
def is_for_episode(self) -> bool:
|
||||
"""Check if this subtitle is for a TV show episode."""
|
||||
return self.season_number is not None and self.episode_number is not None
|
||||
|
||||
|
||||
def get_filename(self) -> str:
|
||||
"""
|
||||
Get the suggested filename for this subtitle.
|
||||
|
||||
|
||||
Format for movies: "Movie.Title.{lang}.{format}"
|
||||
Format for episodes: "S01E05.{lang}.{format}"
|
||||
"""
|
||||
@@ -74,20 +77,20 @@ class Subtitle:
|
||||
else:
|
||||
# For movies, use the file path stem
|
||||
base = self.file_path.value.stem
|
||||
|
||||
|
||||
parts = [base, self.language.value]
|
||||
|
||||
|
||||
if self.hearing_impaired:
|
||||
parts.append("hi")
|
||||
if self.forced:
|
||||
parts.append("forced")
|
||||
|
||||
|
||||
return f"{'.'.join(parts)}.{self.format.value}"
|
||||
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.is_for_episode():
|
||||
return f"Subtitle S{self.season_number:02d}E{self.episode_number:02d} ({self.language.value})"
|
||||
return f"Subtitle ({self.language.value})"
|
||||
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Subtitle(media={self.media_imdb_id}, lang={self.language.value})"
|
||||
|
||||
Reference in New Issue
Block a user