|
from smolagents import tool |
|
import streamlit as st |
|
import requests |
|
import pandas as pd |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@tool |
|
def add_anime(anime_id: int, status:str = "Watching", episodes_watched: int = 0, score: int = 0) -> str: |
|
""" |
|
Add an anime to your MyAnimeList. |
|
Args: |
|
anime_id (int): The ID of the anime to add. |
|
status (str): The status of the anime (e.g., "Watching", "Completed", "On-Hold", "Dropped", "Plan to Watch"). |
|
episodes_watched (int): The number of episodes watched. |
|
score (int): Your score for the anime (0-10). |
|
Returns: |
|
str: A message indicating the success or failure of the operation. |
|
""" |
|
try: |
|
response = requests.patch( |
|
f"https://api.myanimelist.net/v2/anime/{anime_id}/my_list_status", |
|
headers={ |
|
"Authorization": f"Bearer {st.session_state.access_token}", |
|
"Content-Type": "application/x-www-form-urlencoded" |
|
}, |
|
data={ |
|
"status": status, |
|
"num_watched_episodes": episodes_watched, |
|
"score": score |
|
} |
|
) |
|
response.raise_for_status() |
|
return "Anime added/updated successfully!" |
|
except Exception as e: |
|
return f"Failed to add anime: {str(e)}" |
|
|
|
@tool |
|
def remove_anime(anime_id: int) -> str: |
|
""" |
|
Remove an anime from your MyAnimeList. |
|
Args: |
|
anime_id (int): The ID of the anime to remove. |
|
Returns: |
|
str: A message indicating the success or failure of the operation. |
|
""" |
|
try: |
|
response = requests.delete( |
|
f"https://api.myanimelist.net/v2/anime/{anime_id}/my_list_status", |
|
headers={ |
|
"Authorization": f"Bearer {st.session_state.access_token}", |
|
} |
|
) |
|
response.raise_for_status() |
|
return "Anime removed successfully!" |
|
except Exception as e: |
|
return f"Failed to remove anime: {e}" |
|
|
|
@tool |
|
def get_anime_list(status_filter: str = None) -> str: |
|
""" |
|
Get the list of anime in your MyAnimeList. |
|
Args: |
|
status_filter (str): Filter by status (e.g., "Watching", "Completed", "On-Hold", "Dropped", "Plan to Watch"). |
|
Returns: |
|
str: A markdown table representation of the anime list with columns: Name, Status, Episodes Watched, Total Episodes, and Score. |
|
""" |
|
try: |
|
params = { |
|
"fields": "list_status,media_type,num_episodes", |
|
"limit": 100 |
|
} |
|
if status_filter: |
|
params["status"] = status_filter.lower().replace(" ", "_") |
|
|
|
response = requests.get( |
|
"https://api.myanimelist.net/v2/users/@me/animelist", |
|
headers={"Authorization": f"Bearer {st.session_state.access_token}"}, |
|
params=params |
|
) |
|
response.raise_for_status() |
|
return format_anime_list(response.json().get("data", [])) |
|
except Exception as e: |
|
return f"Error fetching list: {str(e)}" |
|
|
|
|
|
@tool |
|
def search_anime(query: str) -> str: |
|
""" |
|
Search for anime by title. |
|
Args: |
|
query (str): The title of the anime to search for. |
|
Returns: |
|
str: A string representation of the search results. |
|
""" |
|
try: |
|
response = requests.get( |
|
"https://api.myanimelist.net/v2/anime", |
|
headers={ |
|
"Authorization": f"Bearer {st.session_state.access_token}", |
|
}, |
|
params={ |
|
"q": query, |
|
"limit": 10 |
|
} |
|
) |
|
response.raise_for_status() |
|
return response.json() |
|
except Exception as e: |
|
return f"Failed to search anime: {e}" |
|
|
|
@tool |
|
def format_anime_list(anime_list: list) -> str: |
|
""" |
|
Format the anime list as a markdown table. |
|
Args: |
|
anime_list (list): The list of anime entries. |
|
Returns: |
|
str: A markdown table representation of the anime list with columns: Name, Status, Episodes Watched, Total Episodes, and Score. |
|
""" |
|
if not anime_list: |
|
return "No anime found." |
|
|
|
|
|
table = "| Name | Status | Episodes Watched | Total Episodes | Score |\n" |
|
table += "|------|--------|------------------|----------------|-------|\n" |
|
|
|
|
|
for entry in anime_list: |
|
anime = entry["node"] |
|
list_status = entry["list_status"] |
|
|
|
title = anime["title"] |
|
status = list_status["status"].replace("_", " ").title() |
|
episodes_watched = list_status["num_episodes_watched"] |
|
total_episodes = anime.get("num_episodes", "Unknown") |
|
score = list_status.get("score", "Not Rated") |
|
|
|
|
|
score_display = str(score) if score and score > 0 else "Not Rated" |
|
|
|
|
|
title_escaped = title.replace("|", "\\|") |
|
|
|
table += f"| {title_escaped} | {status} | {episodes_watched} | {total_episodes} | {score_display} |\n" |
|
|
|
return table |
|
@tool |
|
def display_anime_cards(search_results: list[dict]) -> str: |
|
""" |
|
Render a list of anime search results as visually formatted cards using Streamlit. |
|
|
|
This function displays multiple anime entries in a structured, scrollable layout, |
|
where each anime is presented as a card with its cover image, title (linked to detail page), |
|
rating, episode count, and a truncated synopsis. Designed for use in interactive applications |
|
like SmolAgents, this enhances user experience by presenting search data in an intuitive format. |
|
|
|
Args: |
|
search_results (list[dict]): A list of dictionaries, where each dictionary contains metadata |
|
for a single anime. Expected keys in each dictionary: |
|
- title (str): Title of the anime. |
|
- cover_image (str): URL of the anime’s cover/poster image. |
|
- rating (float): Average rating (0.0 to 10.0 scale). |
|
- episodes (int): Total number of episodes. |
|
- synopsis (str): Brief plot summary. |
|
- url (str): Link to the anime’s full detail page. |
|
|
|
Returns: |
|
None: The function does not return any value. |
|
It directly renders UI components using the Streamlit. |
|
|
|
Example: |
|
search_results = [ |
|
{ |
|
"title": "Naruto", |
|
"cover_image": "https://cdn.example.com/naruto.jpg", |
|
"rating": 7.9, |
|
"episodes": 220, |
|
"synopsis": "A young ninja strives to become Hokage...", |
|
"url": "https://myanimelist.net/anime/20/Naruto" |
|
}, |
|
... |
|
] |
|
display_anime_cards(search_results) |
|
""" |
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@tool |
|
def hianime_watchlink(query: str) -> str: |
|
""" |
|
Search for a HiAnime watch link for the anime in query make Sure its hianime.sx link. |
|
Args: |
|
query (str): The title of the anime to search for. |
|
Returns: |
|
str: A string representation of the hianime watch link or an error message. |
|
""" |
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@tool |
|
def anime_suggestion(query: str) -> str: |
|
""" |
|
Suggest an anime based on a query. |
|
Args: |
|
query (str): The title or description of the anime to suggest. |
|
Returns: |
|
str: A tabular representation of the suggested anime or an error message, this suggestion than searched through search_anime tool to get more information. |
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pass |
|
|