File size: 6,348 Bytes
9b5b26a
 
 
 
c19d193
6aae614
5180720
 
 
 
 
 
8fe992b
9b5b26a
 
5180720
 
 
 
 
 
 
 
9b5b26a
5180720
 
9b5b26a
5180720
9b5b26a
5180720
 
 
 
 
9b5b26a
5180720
9b5b26a
5180720
 
 
9b5b26a
5180720
9b5b26a
 
5180720
 
 
 
 
 
 
 
 
 
 
9b5b26a
5180720
 
8c01ffb
5180720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c01ffb
5180720
6aae614
ae7a494
 
 
 
e121372
bf6d34c
 
29ec968
fe328e0
13d500a
8c01ffb
 
9b5b26a
 
8c01ffb
861422e
 
9b5b26a
8c01ffb
8fe992b
5180720
8c01ffb
 
 
 
 
 
861422e
8fe992b
 
9b5b26a
8c01ffb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
import datetime
import requests
import pytz
import yaml
from tools.final_answer import FinalAnswerTool
import smtplib
import os
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage

from Gradio_UI import GradioUI


# Aux function to help tools with timezone
def _get_now_in_timezone(timezone: str) -> datetime.datetime:
    """Helper: return actual datetime in timezone."""
    tz = pytz.timezone(timezone)
    return datetime.datetime.now(tz)

# Tool 1
@tool
def get_current_time_in_timezone(timezone: str) -> str:
    """Fetches the current local time in a specified timezone.
    Args:
        timezone: A valid timezone string (e.g., 'Europe/Madrid', 'America/New_York').
    """
    try:
        now = _get_now_in_timezone(timezone)
        return f"The current local time in {timezone} is: {now.strftime('%Y-%m-%d %H:%M:%S')}"
    except Exception as e:
        return f"Error fetching time for timezone '{timezone}': {str(e)}"

# tool 2
@tool
def get_day_of_year(timezone: str) -> str:
    """Returns what day of the year it currently is in the given timezone,
    and whether it is New Year's Day (January 1st at midnight).
    Args:
        timezone: A valid timezone string (e.g., 'Europe/Madrid', 'America/New_York').
    """
    try:
        now = _get_now_in_timezone(timezone)  # 👈 reutiliza la lógica
        day_of_year = now.timetuple().tm_yday
        is_leap = now.year % 4 == 0 and (now.year % 100 != 0 or now.year % 400 == 0)
        total_days = 366 if is_leap else 365
        is_new_year_midnight = (now.month == 1 and now.day == 1 and now.hour == 0)

        return (
            f"In {timezone}: day {day_of_year} of {total_days} "
            f"({now.strftime('%B %d, %Y %H:%M:%S')}). "
            f"Is New Year midnight: {is_new_year_midnight}."
        )
    except Exception as e:
        return f"Error: {str(e)}"


# tool 3
@tool
def send_new_year_greeting(
    recipient_name: str,
    recipient_email: str,
    personalized_message: str,
    timezone: str,
    image_base64: str = "",
) -> str:
    """Sends a personalized New Year's greeting email with an optional AI-generated image.
    ONLY sends if it is currently January 1st between 00:00 and 00:59 in the given timezone.
    The agent should first use get_day_of_year to verify the date before calling this.

    Args:
        recipient_name: Full name of the recipient.
        recipient_email: Email address of the recipient.
        personalized_message: Warm, personalized message crafted by the agent for this person.
        timezone: Timezone to check for New Year's midnight (e.g., 'Europe/Madrid').
        image_base64: Optional base64-encoded image generated by image_generation_tool to attach.
    """
    try:
        # helper reused to get timezone
        now = _get_now_in_timezone(timezone) 
        is_new_year_midnight = (now.month == 1 and now.day == 1 and now.hour == 0)

        if not is_new_year_midnight:
            return (
                f"NOT sent. In {timezone} it is {now.strftime('%B %d, %Y %H:%M')} — "
                f"greetings only go out on January 1st at midnight. "
                f"Use get_day_of_year to check first!"
            )

        # email envs vars
        sender_email = os.environ.get("GREETING_SENDER_EMAIL")
        sender_password = os.environ.get("GREETING_SENDER_PASS")  

        if not sender_email or not sender_password:
            return "Missing env vars: GREETING_SENDER_EMAIL and GREETING_SENDER_PASS"

        msg = MIMEMultipart("related")
        msg["Subject"] = f"Happy New Year {now.year}, {recipient_name}!"
        msg["From"] = sender_email
        msg["To"] = recipient_email

        html_body = f"""
        <html><body style="font-family: Arial, sans-serif; max-width: 600px; margin: auto; padding: 20px;">
            <h1 style="color: #FFD700; text-align: center;">🎉 Happy New Year {now.year}!</h1>
            {"<img src='cid:new_year_image' style='width:100%; border-radius:12px; margin-bottom:20px;'/>" if image_base64 else ""}
            <p>Dear <strong>{recipient_name}</strong>,</p>
            <p style="font-size: 16px; line-height: 1.6;">{personalized_message}</p>
            <p style="color: #888; font-size: 12px; text-align:center;">
                Sent with love <3 · {timezone}
            </p>
        </body></html>
        """
        msg.attach(MIMEText(html_body, "html"))

        # image if agent generate it
        if image_base64:
            img_data = base64.b64decode(image_base64)
            img = MIMEImage(img_data)
            img.add_header("Content-ID", "<new_year_image>")
            msg.attach(img)

        with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
            server.login(sender_email, sender_password)
            server.sendmail(sender_email, recipient_email, msg.as_string())

        return (
            f"Greeting sent to {recipient_name} ({recipient_email}) "
            f"at {now.strftime('%H:%M:%S')} in {timezone}!"
            f"{' Includes AI-generated image ' if image_base64 else ''}"
        )

    except Exception as e:
        return f"Failed: {str(e)}"

        
final_answer = FinalAnswerTool()

# If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud' 

model = HfApiModel(
max_tokens=2096,
temperature=0.5,
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
custom_role_conversions=None,
)


# Import tool from Hub
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)

with open("prompts.yaml", 'r') as stream:
    prompt_templates = yaml.safe_load(stream)
    
agent = CodeAgent(
    model=model,
    tools=[final_answer, get_current_time_in_timezone, get_day_of_year, send_new_year_greeting, image_generation_tool], ## add your tools here (don't remove final answer)
    max_steps=6,
    verbosity_level=1,
    grammar=None,
    planning_interval=None,
    name=None,
    description=None,
    prompt_templates=prompt_templates
)


GradioUI(agent).launch()