import os import uuid import requests import hashlib from agno.tools import tool from pathlib import Path from datetime import datetime @tool( name="deploy_html_file_with_digest", # Custom name for the tool (otherwise the function name is used) description="Deploys the generated HTML File to Netlify", # Custom description (otherwise the function docstring is used) show_result=True, # Show result after function call stop_after_tool_call=True, # Return the result immediately after the tool call and stop the agent cache_results=True, # Enable caching of results cache_dir="/tmp/agno_cache", # Custom cache directory cache_ttl=3600, # Cache TTL in seconds (1 hour) ) def deploy_html_file_with_digest(title, html_file_path, access_token=None): """ Deploy a single HTML file to Netlify using the file digest method. Args: title (str): The title/name for the site html_file_path (str): Path to the HTML file to deploy access_token (str): Netlify personal access token (optional, will use env var if not provided) Returns: dict: Response containing site information and deploy details """ # Use provided token or get from environment token = access_token or os.getenv("NETLIFY_PERSONAL_ACCESS_TOKEN") if not token: raise ValueError("No Netlify access token provided") # Generate a random site name site_name = f"{title.lower().replace(' ', '-')}-{str(uuid.uuid4())[:8]}" # Netlify API base URL api_base = "https://api.netlify.com/api/v1" # Headers for authentication headers = { "Authorization": f"Bearer {token}", "User-Agent": "MicrositePilot-Deployer", "Content-Type": "application/json", } try: # Step 1: Create a new site site_data = { "name": site_name, "processing_settings": {"html": {"pretty_urls": True}}, } site_response = requests.post( f"{api_base}/sites", headers=headers, json=site_data ) site_response.raise_for_status() site_info = site_response.json() site_id = site_info["id"] site_url = site_info["url"] admin_url = site_info["admin_url"] # Step 2: Read the HTML file and calculate SHA1 with open(html_file_path, "rb") as f: html_content = f.read() # Calculate SHA1 hash sha1_hash = hashlib.sha1(html_content).hexdigest() # Step 3: Create deployment with file digest deploy_data = {"files": {"/index.html": sha1_hash}} deploy_response = requests.post( f"{api_base}/sites/{site_id}/deploys", headers=headers, json=deploy_data, ) deploy_response.raise_for_status() deploy_info = deploy_response.json() deploy_id = deploy_info["id"] required_files = deploy_info.get("required", []) deploy_url = deploy_info.get("deploy_url", "") deploy_state = deploy_info.get("state", "unknown") # Step 4: Upload required files if sha1_hash in required_files: file_headers = { "Authorization": f"Bearer {token}", "Content-Type": "text/html", "User-Agent": "MicrositePilot-Deployer", } upload_response = requests.put( f"{api_base}/deploys/{deploy_id}/files/index.html", headers=file_headers, data=html_content, ) upload_response.raise_for_status() print(f"✅ File uploaded successfully!") else: print(f"ℹ️ File already exists on Netlify, no upload needed") # Step 5: Check final deployment status status_response = requests.get( f"{api_base}/deploys/{deploy_id}", headers=headers ) status_response.raise_for_status() status_info = status_response.json() final_state = status_info.get("state", "unknown") final_url = status_info.get("deploy_url", deploy_url) # Return comprehensive information return { "success": True, "site": { "id": site_id, "name": site_name, "url": site_url, "admin_url": admin_url, }, } except requests.exceptions.RequestException as e: return { "success": False, "error": str(e), "message": f"Failed to deploy {title}", } except FileNotFoundError: return { "success": False, "error": "File not found", "message": f"HTML file {html_file_path} not found", } except Exception as e: return { "success": False, "error": str(e), "message": f"Unexpected error during deployment of {title}", } @tool( name="save_html_file", description="Saves the html content into a html file", show_result=False, # Don't show result to avoid contaminating agent output ) def save_html_to_file(html_content: str) -> str: """ Manually save HTML content to the microsites directory. Args: html_content: The HTML content to save Returns: str: The full path to the saved HTML file """ # Create microsites directory if it doesn't exist microsites_dir = Path(__file__).parent.parent / "microsites" microsites_dir.mkdir(exist_ok=True) # Generate filename with timestamp timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"demo_{timestamp}.html" file_path = microsites_dir / filename try: # Write HTML content to file with open(file_path, "w", encoding="utf-8") as f: f.write(html_content) return str(file_path) except Exception as e: raise Exception(f"Could not save HTML file: {e}")