From b45b603b97262bcdf25c9dc62fe4ecbfd881c80b Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 1 Nov 2025 12:01:48 +0800 Subject: [PATCH] fix agent tools --- app/agent/tools/Agent Tools v1.0.json | 297 -------------------- app/agent/tools/base.py | 8 +- app/agent/tools/impl/add_download.py | 19 +- app/agent/tools/impl/add_subscribe.py | 19 +- app/agent/tools/impl/get_recommendations.py | 17 +- app/agent/tools/impl/query_downloaders.py | 13 +- app/agent/tools/impl/query_downloads.py | 16 +- app/agent/tools/impl/query_media_library.py | 17 +- app/agent/tools/impl/query_subscribes.py | 17 +- app/agent/tools/impl/search_media.py | 18 +- app/agent/tools/impl/search_torrents.py | 19 +- app/agent/tools/impl/send_message.py | 16 +- 12 files changed, 145 insertions(+), 331 deletions(-) delete mode 100644 app/agent/tools/Agent Tools v1.0.json diff --git a/app/agent/tools/Agent Tools v1.0.json b/app/agent/tools/Agent Tools v1.0.json deleted file mode 100644 index 6059a3a9..00000000 --- a/app/agent/tools/Agent Tools v1.0.json +++ /dev/null @@ -1,297 +0,0 @@ -[ - { - "description": "Search for media resources including movies, TV shows, anime, etc. Supports searching by title, year, type, and other criteria. Returns detailed media information from TMDB database.", - "name": "search_media", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "title": { - "description": "The title of the media to search for (e.g., 'The Matrix', 'Breaking Bad')", - "type": "string" - }, - "year": { - "description": "Release year of the media (optional, helps narrow down results)", - "type": "string" - }, - "media_type": { - "description": "Type of media content: 'movie' for films, 'tv' for television series, 'anime' for anime series", - "type": "string" - }, - "season": { - "description": "Season number for TV shows and anime (optional, only applicable for series)", - "type": "integer" - } - }, - "required": [ - "title", - "explanation" - ], - "type": "object" - } - }, - { - "description": "Add media subscription to create automated download rules for movies and TV shows. The system will automatically search and download new episodes or releases based on the subscription criteria.", - "name": "add_subscribe", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "title": { - "description": "The title of the media to subscribe to (e.g., 'The Matrix', 'Breaking Bad')", - "type": "string" - }, - "year": { - "description": "Release year of the media (required for accurate identification)", - "type": "string" - }, - "media_type": { - "description": "Type of media content: 'movie' for films, 'tv' for television series", - "type": "string" - }, - "season": { - "description": "Season number for TV shows (optional, if not specified will subscribe to all seasons)", - "type": "integer" - }, - "tmdb_id": { - "description": "TMDB database ID for precise media identification (optional but recommended for accuracy)", - "type": "string" - } - }, - "required": [ - "title", - "year", - "media_type", - "explanation" - ], - "type": "object" - } - }, - { - "description": "Search for torrent files across configured indexer sites based on media information. Returns available torrent downloads with details like file size, quality, and download links.", - "name": "search_torrents", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "title": { - "description": "The title of the media resource to search for (e.g., 'The Matrix 1999', 'Breaking Bad S01E01')", - "type": "string" - }, - "year": { - "description": "Release year of the media (optional, helps narrow down search results)", - "type": "string" - }, - "media_type": { - "description": "Type of media content: 'movie' for films, 'tv' for television series", - "type": "string" - }, - "season": { - "description": "Season number for TV shows (optional, only applicable for series)", - "type": "integer" - }, - "sites": { - "description": "Array of specific site IDs to search on (optional, if not provided searches all configured sites)", - "items": { - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "title", - "explanation" - ], - "type": "object" - } - }, - { - "description": "Add torrent download task to the configured downloader (qBittorrent, Transmission, etc.). Downloads the torrent file and starts the download process with specified settings.", - "name": "add_download", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "torrent_title": { - "description": "The display name/title of the torrent (e.g., 'The.Matrix.1999.1080p.BluRay.x264')", - "type": "string" - }, - "torrent_url": { - "description": "Direct URL to the torrent file (.torrent) or magnet link", - "type": "string" - }, - "downloader": { - "description": "Name of the downloader to use (optional, uses default if not specified)", - "type": "string" - }, - "save_path": { - "description": "Directory path where the downloaded files should be saved (optional, uses default path if not specified)", - "type": "string" - }, - "labels": { - "description": "Comma-separated list of labels/tags to assign to the download (optional, e.g., 'movie,hd,bluray')", - "type": "string" - } - }, - "required": [ - "torrent_title", - "torrent_url", - "explanation" - ], - "type": "object" - } - }, - { - "description": "Query subscription status and list all user subscriptions. Shows active subscriptions, their download status, and configuration details.", - "name": "query_subscribes", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "status": { - "description": "Filter subscriptions by status: 'active' for enabled subscriptions, 'inactive' for disabled ones, 'all' for all subscriptions", - "type": "string" - }, - "media_type": { - "description": "Filter by media type: 'movie' for films, 'tv' for television series, 'all' for all types", - "type": "string" - } - }, - "required": [ - "explanation" - ], - "type": "object" - } - }, - { - "description": "Query download status and list all active download tasks. Shows download progress, completion status, and task details from configured downloaders.", - "name": "query_downloads", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "downloader": { - "description": "Name of specific downloader to query (optional, if not provided queries all configured downloaders)", - "type": "string" - }, - "status": { - "description": "Filter downloads by status: 'downloading' for active downloads, 'completed' for finished downloads, 'paused' for paused downloads, 'all' for all downloads", - "type": "string" - } - }, - "required": [ - "explanation" - ], - "type": "object" - } - }, - { - "description": "Query downloader configuration and list all available downloaders. Shows downloader status, connection details, and configuration settings.", - "name": "query_downloaders", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - } - }, - "required": [ - "explanation" - ], - "type": "object" - } - }, - { - "description": "Get trending and popular media recommendations from various sources. Returns curated lists of popular movies, TV shows, and anime based on different criteria like trending, ratings, or calendar schedules.", - "name": "get_recommendations", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "source": { - "description": "Recommendation source: 'tmdb_trending' for TMDB trending content, 'douban_hot' for Douban popular content, 'bangumi_calendar' for Bangumi anime calendar", - "type": "string" - }, - "media_type": { - "description": "Type of media content: 'movie' for films, 'tv' for television series, 'all' for all types", - "type": "string" - }, - "limit": { - "description": "Maximum number of recommendations to return (default: 20, maximum: 100)", - "type": "integer" - } - }, - "required": [ - "explanation" - ], - "type": "object" - } - }, - { - "description": "Query media library status and list all media files that have been successfully processed and added to the media server (Plex, Emby, Jellyfin). Shows library statistics and file details.", - "name": "query_media_library", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "media_type": { - "description": "Type of media content: 'movie' for films, 'tv' for television series, 'all' for all types", - "type": "string" - }, - "title": { - "description": "Specific media title to search for (optional, if provided returns detailed info for that specific media)", - "type": "string" - }, - "year": { - "description": "Release year of the media (optional, helps narrow down search results)", - "type": "string" - } - }, - "required": [ - "explanation" - ], - "type": "object" - } - }, - { - "description": "Send notification message to the user through configured notification channels (Telegram, Slack, WeChat, etc.). Used to inform users about operation results, errors, or important updates.", - "name": "send_message", - "parameters": { - "properties": { - "explanation": { - "description": "Clear explanation of why this tool is being used in the current context", - "type": "string" - }, - "message": { - "description": "The message content to send to the user (should be clear and informative)", - "type": "string" - }, - "message_type": { - "description": "Type of message: 'info' for general information, 'success' for successful operations, 'warning' for warnings, 'error' for error messages", - "type": "string" - } - }, - "required": [ - "message", - "explanation" - ], - "type": "object" - } - } -] \ No newline at end of file diff --git a/app/agent/tools/base.py b/app/agent/tools/base.py index ac3b1dfc..8881cc95 100644 --- a/app/agent/tools/base.py +++ b/app/agent/tools/base.py @@ -41,10 +41,10 @@ class MoviePilotTool(BaseTool): """发送工具消息""" ToolChain().post_message( Notification( - channel=self.channel, - source=self.source, - userid=self.user_id, - username=self.username, + channel=self._channel, + source=self._source, + userid=self._user_id, + username=self._username, title=title, text=message ) diff --git a/app/agent/tools/impl/add_download.py b/app/agent/tools/impl/add_download.py index ee1c2910..b27e472d 100644 --- a/app/agent/tools/impl/add_download.py +++ b/app/agent/tools/impl/add_download.py @@ -1,6 +1,8 @@ """添加下载工具""" -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.chain.download import DownloadChain @@ -10,11 +12,22 @@ from app.log import logger from app.schemas import TorrentInfo +class AddDownloadInput(BaseModel): + """添加下载工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + torrent_title: str = Field(..., description="The display name/title of the torrent (e.g., 'The.Matrix.1999.1080p.BluRay.x264')") + torrent_url: str = Field(..., description="Direct URL to the torrent file (.torrent) or magnet link") + downloader: Optional[str] = Field(None, description="Name of the downloader to use (optional, uses default if not specified)") + save_path: Optional[str] = Field(None, description="Directory path where the downloaded files should be saved (optional, uses default path if not specified)") + labels: Optional[str] = Field(None, description="Comma-separated list of labels/tags to assign to the download (optional, e.g., 'movie,hd,bluray')") + + class AddDownloadTool(MoviePilotTool): name: str = "add_download" - description: str = "添加下载任务,将搜索到的种子资源添加到下载器。" + description: str = "Add torrent download task to the configured downloader (qBittorrent, Transmission, etc.). Downloads the torrent file and starts the download process with specified settings." + args_schema: Type[BaseModel] = AddDownloadInput - async def _arun(self, torrent_title: str, torrent_url: str, explanation: str, + async def _arun(self, torrent_title: str, torrent_url: str, downloader: Optional[str] = None, save_path: Optional[str] = None, labels: Optional[str] = None, **kwargs) -> str: logger.info( diff --git a/app/agent/tools/impl/add_subscribe.py b/app/agent/tools/impl/add_subscribe.py index 791f95f2..b1bc6c3e 100644 --- a/app/agent/tools/impl/add_subscribe.py +++ b/app/agent/tools/impl/add_subscribe.py @@ -1,6 +1,8 @@ """添加订阅工具""" -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.chain.subscribe import SubscribeChain @@ -8,11 +10,22 @@ from app.log import logger from app.schemas.types import MediaType +class AddSubscribeInput(BaseModel): + """添加订阅工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + title: str = Field(..., description="The title of the media to subscribe to (e.g., 'The Matrix', 'Breaking Bad')") + year: str = Field(..., description="Release year of the media (required for accurate identification)") + media_type: str = Field(..., description="Type of media content: 'movie' for films, 'tv' for television series") + season: Optional[int] = Field(None, description="Season number for TV shows (optional, if not specified will subscribe to all seasons)") + tmdb_id: Optional[str] = Field(None, description="TMDB database ID for precise media identification (optional but recommended for accuracy)") + + class AddSubscribeTool(MoviePilotTool): name: str = "add_subscribe" - description: str = "添加媒体订阅,为用户感兴趣的媒体内容创建订阅规则。" + description: str = "Add media subscription to create automated download rules for movies and TV shows. The system will automatically search and download new episodes or releases based on the subscription criteria." + args_schema: Type[BaseModel] = AddSubscribeInput - async def _arun(self, title: str, year: str, media_type: str, explanation: str, + async def _arun(self, title: str, year: str, media_type: str, season: Optional[int] = None, tmdb_id: Optional[str] = None, **kwargs) -> str: logger.info( f"执行工具: {self.name}, 参数: title={title}, year={year}, media_type={media_type}, season={season}, tmdb_id={tmdb_id}") diff --git a/app/agent/tools/impl/get_recommendations.py b/app/agent/tools/impl/get_recommendations.py index 5e16f2c9..bfbfcced 100644 --- a/app/agent/tools/impl/get_recommendations.py +++ b/app/agent/tools/impl/get_recommendations.py @@ -1,18 +1,29 @@ """获取推荐工具""" import json -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.chain.recommend import RecommendChain from app.log import logger from app.agent.tools.base import MoviePilotTool +class GetRecommendationsInput(BaseModel): + """获取推荐工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + source: Optional[str] = Field("tmdb_trending", description="Recommendation source: 'tmdb_trending' for TMDB trending content, 'douban_hot' for Douban popular content, 'bangumi_calendar' for Bangumi anime calendar") + media_type: Optional[str] = Field("all", description="Type of media content: 'movie' for films, 'tv' for television series, 'all' for all types") + limit: Optional[int] = Field(20, description="Maximum number of recommendations to return (default: 20, maximum: 100)") + + class GetRecommendationsTool(MoviePilotTool): name: str = "get_recommendations" - description: str = "获取热门媒体推荐,包括电影、电视剧等热门内容。" + description: str = "Get trending and popular media recommendations from various sources. Returns curated lists of popular movies, TV shows, and anime based on different criteria like trending, ratings, or calendar schedules." + args_schema: Type[BaseModel] = GetRecommendationsInput - async def _arun(self, explanation: str, source: Optional[str] = "tmdb_trending", + async def _arun(self, source: Optional[str] = "tmdb_trending", media_type: Optional[str] = "all", limit: Optional[int] = 20, **kwargs) -> str: logger.info(f"执行工具: {self.name}, 参数: source={source}, media_type={media_type}, limit={limit}") try: diff --git a/app/agent/tools/impl/query_downloaders.py b/app/agent/tools/impl/query_downloaders.py index 725214eb..e7a36b69 100644 --- a/app/agent/tools/impl/query_downloaders.py +++ b/app/agent/tools/impl/query_downloaders.py @@ -1,6 +1,9 @@ """查询下载器工具""" import json +from typing import Type + +from pydantic import BaseModel, Field from app.db.systemconfig_oper import SystemConfigOper from app.log import logger @@ -8,11 +11,17 @@ from app.schemas.types import SystemConfigKey from app.agent.tools.base import MoviePilotTool +class QueryDownloadersInput(BaseModel): + """查询下载器工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + + class QueryDownloadersTool(MoviePilotTool): name: str = "query_downloaders" - description: str = "查询下载器配置,查看可用的下载器列表和配置信息。" + description: str = "Query downloader configuration and list all available downloaders. Shows downloader status, connection details, and configuration settings." + args_schema: Type[BaseModel] = QueryDownloadersInput - async def _arun(self, explanation: str, **kwargs) -> str: + async def _arun(self, **kwargs) -> str: logger.info(f"执行工具: {self.name}") try: system_config_oper = SystemConfigOper() diff --git a/app/agent/tools/impl/query_downloads.py b/app/agent/tools/impl/query_downloads.py index 219309fa..c24125c1 100644 --- a/app/agent/tools/impl/query_downloads.py +++ b/app/agent/tools/impl/query_downloads.py @@ -1,18 +1,28 @@ """查询下载工具""" import json -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.chain.download import DownloadChain from app.log import logger from app.agent.tools.base import MoviePilotTool +class QueryDownloadsInput(BaseModel): + """查询下载工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + downloader: Optional[str] = Field(None, description="Name of specific downloader to query (optional, if not provided queries all configured downloaders)") + status: Optional[str] = Field("all", description="Filter downloads by status: 'downloading' for active downloads, 'completed' for finished downloads, 'paused' for paused downloads, 'all' for all downloads") + + class QueryDownloadsTool(MoviePilotTool): name: str = "query_downloads" - description: str = "查询下载状态,查看下载器的任务列表和进度。" + description: str = "Query download status and list all active download tasks. Shows download progress, completion status, and task details from configured downloaders." + args_schema: Type[BaseModel] = QueryDownloadsInput - async def _arun(self, explanation: str, downloader: Optional[str] = None, + async def _arun(self, downloader: Optional[str] = None, status: Optional[str] = "all", **kwargs) -> str: logger.info(f"执行工具: {self.name}, 参数: downloader={downloader}, status={status}") try: diff --git a/app/agent/tools/impl/query_media_library.py b/app/agent/tools/impl/query_media_library.py index a73e26e6..6b22ea42 100644 --- a/app/agent/tools/impl/query_media_library.py +++ b/app/agent/tools/impl/query_media_library.py @@ -1,7 +1,9 @@ """查询媒体库工具""" import json -from typing import Optional, List +from typing import Optional, List, Type + +from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.db.mediaserver_oper import MediaServerOper @@ -9,11 +11,20 @@ from app.log import logger from app.schemas import MediaServerItem +class QueryMediaLibraryInput(BaseModel): + """查询媒体库工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + media_type: Optional[str] = Field("all", description="Type of media content: 'movie' for films, 'tv' for television series, 'all' for all types") + title: Optional[str] = Field(None, description="Specific media title to search for (optional, if provided returns detailed info for that specific media)") + year: Optional[str] = Field(None, description="Release year of the media (optional, helps narrow down search results)") + + class QueryMediaLibraryTool(MoviePilotTool): name: str = "query_media_library" - description: str = "查询媒体库状态,查看已入库的媒体文件情况。" + description: str = "Query media library status and list all media files that have been successfully processed and added to the media server (Plex, Emby, Jellyfin). Shows library statistics and file details." + args_schema: Type[BaseModel] = QueryMediaLibraryInput - async def _arun(self, explanation: str, media_type: Optional[str] = "all", + async def _arun(self, media_type: Optional[str] = "all", title: Optional[str] = None, year: Optional[str] = None, **kwargs) -> str: logger.info(f"执行工具: {self.name}, 参数: media_type={media_type}, title={title}") try: diff --git a/app/agent/tools/impl/query_subscribes.py b/app/agent/tools/impl/query_subscribes.py index 31b2c9fd..6d7d5db0 100644 --- a/app/agent/tools/impl/query_subscribes.py +++ b/app/agent/tools/impl/query_subscribes.py @@ -1,19 +1,28 @@ """查询订阅工具""" import json -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.db.subscribe_oper import SubscribeOper from app.log import logger from app.agent.tools.base import MoviePilotTool +class QuerySubscribesInput(BaseModel): + """查询订阅工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + status: Optional[str] = Field("all", description="Filter subscriptions by status: 'active' for enabled subscriptions, 'inactive' for disabled ones, 'all' for all subscriptions") + media_type: Optional[str] = Field("all", description="Filter by media type: 'movie' for films, 'tv' for television series, 'all' for all types") + + class QuerySubscribesTool(MoviePilotTool): name: str = "query_subscribes" - description: str = "查询订阅状态,查看用户的订阅列表和状态。" + description: str = "Query subscription status and list all user subscriptions. Shows active subscriptions, their download status, and configuration details." + args_schema: Type[BaseModel] = QuerySubscribesInput - async def _arun(self, explanation: str, status: Optional[str] = "all", - media_type: Optional[str] = "all", **kwargs) -> str: + async def _arun(self, status: Optional[str] = "all", media_type: Optional[str] = "all", **kwargs) -> str: logger.info(f"执行工具: {self.name}, 参数: status={status}, media_type={media_type}") try: subscribe_oper = SubscribeOper() diff --git a/app/agent/tools/impl/search_media.py b/app/agent/tools/impl/search_media.py index ca6bb281..b2f871ca 100644 --- a/app/agent/tools/impl/search_media.py +++ b/app/agent/tools/impl/search_media.py @@ -1,7 +1,9 @@ """搜索媒体工具""" import json -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.chain.media import MediaChain @@ -9,11 +11,21 @@ from app.log import logger from app.schemas.types import MediaType +class SearchMediaInput(BaseModel): + """搜索媒体工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + title: str = Field(..., description="The title of the media to search for (e.g., 'The Matrix', 'Breaking Bad')") + year: Optional[str] = Field(None, description="Release year of the media (optional, helps narrow down results)") + media_type: Optional[str] = Field(None, description="Type of media content: 'movie' for films, 'tv' for television series, 'anime' for anime series") + season: Optional[int] = Field(None, description="Season number for TV shows and anime (optional, only applicable for series)") + + class SearchMediaTool(MoviePilotTool): name: str = "search_media" - description: str = "搜索媒体资源,包括电影、电视剧、动漫等。可以根据标题、年份、类型等条件进行搜索。" + description: str = "Search for media resources including movies, TV shows, anime, etc. Supports searching by title, year, type, and other criteria. Returns detailed media information from TMDB database." + args_schema: Type[BaseModel] = SearchMediaInput - async def _arun(self, title: str, explanation: str, year: Optional[str] = None, + async def _arun(self, title: str, year: Optional[str] = None, media_type: Optional[str] = None, season: Optional[int] = None, **kwargs) -> str: logger.info( f"执行工具: {self.name}, 参数: title={title}, year={year}, media_type={media_type}, season={season}") diff --git a/app/agent/tools/impl/search_torrents.py b/app/agent/tools/impl/search_torrents.py index 1ede8ea4..44c1ae09 100644 --- a/app/agent/tools/impl/search_torrents.py +++ b/app/agent/tools/impl/search_torrents.py @@ -1,7 +1,9 @@ """搜索种子工具""" import json -from typing import List, Optional +from typing import List, Optional, Type + +from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.chain.search import SearchChain @@ -9,11 +11,22 @@ from app.log import logger from app.schemas.types import MediaType +class SearchTorrentsInput(BaseModel): + """搜索种子工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + title: str = Field(..., description="The title of the media resource to search for (e.g., 'The Matrix 1999', 'Breaking Bad S01E01')") + year: Optional[str] = Field(None, description="Release year of the media (optional, helps narrow down search results)") + media_type: Optional[str] = Field(None, description="Type of media content: 'movie' for films, 'tv' for television series") + season: Optional[int] = Field(None, description="Season number for TV shows (optional, only applicable for series)") + sites: Optional[List[int]] = Field(None, description="Array of specific site IDs to search on (optional, if not provided searches all configured sites)") + + class SearchTorrentsTool(MoviePilotTool): name: str = "search_torrents" - description: str = "搜索站点种子资源,根据媒体信息搜索可下载的种子文件。" + description: str = "Search for torrent files across configured indexer sites based on media information. Returns available torrent downloads with details like file size, quality, and download links." + args_schema: Type[BaseModel] = SearchTorrentsInput - async def _arun(self, title: str, explanation: str, year: Optional[str] = None, + async def _arun(self, title: str, year: Optional[str] = None, media_type: Optional[str] = None, season: Optional[int] = None, sites: Optional[List[int]] = None, **kwargs) -> str: logger.info( diff --git a/app/agent/tools/impl/send_message.py b/app/agent/tools/impl/send_message.py index 1402bffb..17371be7 100644 --- a/app/agent/tools/impl/send_message.py +++ b/app/agent/tools/impl/send_message.py @@ -1,16 +1,26 @@ """发送消息工具""" -from typing import Optional +from typing import Optional, Type + +from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.log import logger +class SendMessageInput(BaseModel): + """发送消息工具的输入参数模型""" + explanation: str = Field(..., description="Clear explanation of why this tool is being used in the current context") + message: str = Field(..., description="The message content to send to the user (should be clear and informative)") + message_type: Optional[str] = Field("info", description="Type of message: 'info' for general information, 'success' for successful operations, 'warning' for warnings, 'error' for error messages") + + class SendMessageTool(MoviePilotTool): name: str = "send_message" - description: str = "发送消息通知,向用户发送操作结果或重要信息。" + description: str = "Send notification message to the user through configured notification channels (Telegram, Slack, WeChat, etc.). Used to inform users about operation results, errors, or important updates." + args_schema: Type[BaseModel] = SendMessageInput - async def _arun(self, message: str, explanation: str, message_type: Optional[str] = "info", **kwargs) -> str: + async def _arun(self, message: str, message_type: Optional[str] = None, **kwargs) -> str: logger.info(f"执行工具: {self.name}, 参数: message={message}, message_type={message_type}") try: self.send_tool_message(message, title=message_type)