Spaces:
Paused
Paused
| """ | |
| tools.py - Comprehensive tool implementations for unrestricted AI agent web app. | |
| Runs on Hugging Face Spaces with local llama.cpp (Llama 3.1 8B Instruct Q4_K_M). | |
| """ | |
| import os | |
| import sys | |
| import re | |
| import json | |
| import math | |
| import random | |
| import string | |
| import hashlib | |
| import base64 | |
| import uuid | |
| import time | |
| import datetime | |
| import subprocess | |
| import socket | |
| import zipfile | |
| import shutil | |
| import platform | |
| import tempfile | |
| import traceback | |
| import difflib | |
| import html | |
| import urllib.parse | |
| from pathlib import Path | |
| from typing import Dict, Any, List, Optional | |
| # Third-party imports | |
| import requests | |
| from bs4 import BeautifulSoup | |
| import yfinance as yf | |
| from duckduckgo_search import DDGS | |
| import pytesseract | |
| from PIL import Image | |
| import qrcode | |
| from barcode import Code128 | |
| from barcode.writer import ImageWriter | |
| from deep_translator import GoogleTranslator | |
| from reportlab.lib.pagesizes import letter | |
| from reportlab.pdfgen import canvas | |
| from docx import Document | |
| from docx.shared import Pt | |
| import dns.resolver | |
| import psutil | |
| import textblob | |
| from sumy.parsers.plaintext import PlaintextParser | |
| from sumy.nlp.tokenizers import Tokenizer | |
| from sumy.summarizers.lsa import LsaSummarizer | |
| import spacy | |
| import pint | |
| from youtube_transcript_api import YouTubeTranscriptApi | |
| # Local imports | |
| from config import GEMINI_API_KEY | |
| from utils import safe_exec, safe_command_exec, generate_password as utils_generate_password, hash_string | |
| # Initialize spaCy (load once) | |
| try: | |
| nlp = spacy.load("en_core_web_sm") | |
| except Exception: | |
| nlp = None | |
| # Initialize pint unit registry | |
| ureg = pint.UnitRegistry() | |
| # ============================================================================= | |
| # HELPER FUNCTIONS | |
| # ============================================================================= | |
| def _truncate(text: str, max_len: int = 12000) -> str: | |
| """Truncate text if it exceeds max_len characters.""" | |
| if text is None: | |
| return "Error: None result" | |
| if len(text) > max_len: | |
| return text[:max_len] + "\n...[truncated]" | |
| return text | |
| def _error_msg(e: Exception) -> str: | |
| """Format exception into a clean error string.""" | |
| return f"Error: {type(e).__name__}: {str(e)}" | |
| def _human_readable_size(size_bytes: int) -> str: | |
| """Convert bytes to human readable format.""" | |
| for unit in ["B", "KB", "MB", "GB", "TB"]: | |
| if size_bytes < 1024.0: | |
| return f"{size_bytes:.2f} {unit}" | |
| size_bytes /= 1024.0 | |
| return f"{size_bytes:.2f} PB" | |
| # ============================================================================= | |
| # WEB TOOLS | |
| # ============================================================================= | |
| def web_search(query: str, max_results: int = 5) -> str: | |
| """Search the web using DuckDuckGo and return results.""" | |
| try: | |
| max_results = min(int(max_results), 10) | |
| with DDGS() as ddgs: | |
| results = list(ddgs.text(query, max_results=max_results)) | |
| if not results: | |
| return "No results found." | |
| lines = [] | |
| for i, r in enumerate(results, 1): | |
| title = r.get("title", "No title") | |
| href = r.get("href", "No URL") | |
| body = r.get("body", "No description") | |
| lines.append(f"{i}. {title}\n URL: {href}\n {body}") | |
| return "\n\n".join(lines) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def browse_page(url: str) -> str: | |
| """Fetch and extract text content from a web page using requests + BeautifulSoup.""" | |
| try: | |
| headers = { | |
| "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" | |
| } | |
| resp = requests.get(url, headers=headers, timeout=30) | |
| resp.raise_for_status() | |
| soup = BeautifulSoup(resp.text, "html.parser") | |
| for tag in soup(["script", "style", "nav", "footer", "header"]): | |
| tag.decompose() | |
| text = soup.get_text(separator="\n", strip=True) | |
| text = "\n".join(line.strip() for line in text.splitlines() if line.strip()) | |
| return _truncate(text) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def playwright_screenshot(url: str, output_path: str = "/tmp/screenshot.png") -> str: | |
| """Take a screenshot of a webpage using Playwright.""" | |
| try: | |
| from playwright.sync_api import sync_playwright | |
| with sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| page = browser.new_page(viewport={"width": 1280, "height": 720}) | |
| page.goto(url, wait_until="networkidle", timeout=60000) | |
| page.screenshot(path=output_path, full_page=True) | |
| browser.close() | |
| return f"Screenshot saved to: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def playwright_pdf(url: str, output_path: str = "/tmp/page.pdf") -> str: | |
| """Save a webpage as PDF using Playwright.""" | |
| try: | |
| from playwright.sync_api import sync_playwright | |
| with sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| page = browser.new_page() | |
| page.goto(url, wait_until="networkidle", timeout=60000) | |
| page.pdf(path=output_path, format="A4") | |
| browser.close() | |
| return f"PDF saved to: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # DOCUMENT TOOLS | |
| # ============================================================================= | |
| def create_pdf(content: str, output_path: str = "/tmp/output.pdf", title: str = "Document") -> str: | |
| """Create a PDF file from text content using ReportLab.""" | |
| try: | |
| c = canvas.Canvas(output_path, pagesize=letter) | |
| width, height = letter | |
| c.setFont("Helvetica-Bold", 16) | |
| c.drawString(72, height - 72, title) | |
| c.setFont("Helvetica", 12) | |
| y = height - 100 | |
| for line in content.split("\n"): | |
| if y < 72: | |
| c.showPage() | |
| y = height - 72 | |
| c.drawString(72, y, line[:90]) | |
| y -= 14 | |
| c.save() | |
| return f"PDF created: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def create_docx(content: str, output_path: str = "/tmp/output.docx", title: str = "Document") -> str: | |
| """Create a DOCX file from text content using python-docx.""" | |
| try: | |
| doc = Document() | |
| heading = doc.add_heading(title, level=1) | |
| for line in content.split("\n"): | |
| if line.strip(): | |
| p = doc.add_paragraph(line.strip()) | |
| p.style.font.size = Pt(11) | |
| doc.save(output_path) | |
| return f"DOCX created: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # IMAGE TOOLS | |
| # ============================================================================= | |
| def describe_image(image_path: str, prompt: str = "Describe this image in detail.") -> str: | |
| """Describe an image using Gemini Vision API.""" | |
| try: | |
| if not GEMINI_API_KEY: | |
| return "Error: GEMINI_API_KEY not configured in config module." | |
| import google.generativeai as genai | |
| genai.configure(api_key=GEMINI_API_KEY) | |
| model = genai.GenerativeModel("gemini-1.5-flash") | |
| img = Image.open(image_path) | |
| response = model.generate_content([prompt, img]) | |
| return response.text if response.text else "No description generated." | |
| except Exception as e: | |
| return _error_msg(e) | |
| def ocr_image(image_path: str, language: str = "eng") -> str: | |
| """Extract text from an image using pytesseract OCR.""" | |
| try: | |
| img = Image.open(image_path) | |
| text = pytesseract.image_to_string(img, lang=language) | |
| return text.strip() if text.strip() else "No text detected in image." | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # TRANSLATION TOOLS | |
| # ============================================================================= | |
| def translate_text(text: str, target_language: str = "en", source_language: str = "auto") -> str: | |
| """Translate text using deep_translator GoogleTranslator.""" | |
| try: | |
| translator = GoogleTranslator(source=source_language, target=target_language) | |
| result = translator.translate(text) | |
| return result if result else "Translation failed." | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # DATA TOOLS | |
| # ============================================================================= | |
| def get_weather(location: str) -> str: | |
| """Get weather information from wttr.in.""" | |
| try: | |
| url = f"https://wttr.in/{urllib.parse.quote(location)}?format=j1" | |
| resp = requests.get(url, timeout=15) | |
| resp.raise_for_status() | |
| data = resp.json() | |
| current = data["current_condition"][0] | |
| area = data["nearest_area"][0] | |
| loc_name = f"{area['areaName'][0]['value']}, {area['country'][0]['value']}" | |
| temp_c = current["temp_C"] | |
| temp_f = current["temp_F"] | |
| desc = current["weatherDesc"][0]["value"] | |
| humidity = current["humidity"] | |
| wind = current["windspeedKmph"] | |
| return ( | |
| f"Weather for {loc_name}:\n" | |
| f" Temperature: {temp_c}°C / {temp_f}°F\n" | |
| f" Condition: {desc}\n" | |
| f" Humidity: {humidity}%\n" | |
| f" Wind: {wind} km/h" | |
| ) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def get_news(query: str = "latest news", max_results: int = 5) -> str: | |
| """Get news using DuckDuckGo news search.""" | |
| try: | |
| max_results = min(int(max_results), 10) | |
| with DDGS() as ddgs: | |
| results = list(ddgs.news(query, max_results=max_results)) | |
| if not results: | |
| return "No news found." | |
| lines = [] | |
| for i, r in enumerate(results, 1): | |
| title = r.get("title", "No title") | |
| source = r.get("source", "Unknown") | |
| date = r.get("date", "Unknown date") | |
| url = r.get("url", "No URL") | |
| body = r.get("body", "No summary") | |
| lines.append(f"{i}. {title}\n Source: {source} | {date}\n {body}\n URL: {url}") | |
| return "\n\n".join(lines) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def get_stock_price(ticker: str) -> str: | |
| """Get stock price information using yfinance.""" | |
| try: | |
| stock = yf.Ticker(ticker) | |
| info = stock.info | |
| hist = stock.history(period="1d") | |
| if hist.empty: | |
| return f"No data found for ticker: {ticker}" | |
| current = hist["Close"].iloc[-1] | |
| prev_close = info.get("previousClose", current) | |
| change = current - prev_close | |
| change_pct = (change / prev_close * 100) if prev_close else 0 | |
| name = info.get("longName", ticker) | |
| currency = info.get("currency", "USD") | |
| return ( | |
| f"{name} ({ticker})\n" | |
| f" Price: {current:.2f} {currency}\n" | |
| f" Change: {change:+.2f} ({change_pct:+.2f}%)\n" | |
| f" Market Cap: {info.get('marketCap', 'N/A')}\n" | |
| f" 52W High: {info.get('fiftyTwoWeekHigh', 'N/A')}\n" | |
| f" 52W Low: {info.get('fiftyTwoWeekLow', 'N/A')}" | |
| ) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # MATH / CODE TOOLS | |
| # ============================================================================= | |
| def calculator(expression: str) -> str: | |
| """Evaluate a mathematical expression safely using math functions.""" | |
| try: | |
| allowed_names = { | |
| "abs": abs, "round": round, "max": max, "min": min, | |
| "sum": sum, "pow": pow, "len": len, | |
| "sin": math.sin, "cos": math.cos, "tan": math.tan, | |
| "asin": math.asin, "acos": math.acos, "atan": math.atan, | |
| "sinh": math.sinh, "cosh": math.cosh, "tanh": math.tanh, | |
| "exp": math.exp, "log": math.log, "log10": math.log10, | |
| "log2": math.log2, "sqrt": math.sqrt, "ceil": math.ceil, | |
| "floor": math.floor, "factorial": math.factorial, | |
| "pi": math.pi, "e": math.e, "tau": math.tau, | |
| "degrees": math.degrees, "radians": math.radians, | |
| "gcd": math.gcd, "lcm": math.lcm if hasattr(math, "lcm") else None, | |
| "isclose": math.isclose, "inf": math.inf, "nan": math.nan, | |
| } | |
| cleaned = re.sub(r"[^0-9+\-*/().,\s\w]", "", expression) | |
| result = eval(cleaned, {"__builtins__": {}}, allowed_names) | |
| return f"Result: {result}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def python_interpreter(code: str) -> str: | |
| """Execute Python code safely using safe_exec wrapper.""" | |
| try: | |
| result = safe_exec(code) | |
| return _truncate(str(result)) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def execute_command(command: str, timeout: int = 30) -> str: | |
| """Execute a shell command safely with timeout using safe_command_exec.""" | |
| try: | |
| result = safe_command_exec(command, timeout=int(timeout)) | |
| return _truncate(str(result)) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def code_formatter(code: str, language: str = "python") -> str: | |
| """Format code using black (Python only).""" | |
| try: | |
| if language.lower() != "python": | |
| return f"Error: code_formatter only supports Python, not {language}" | |
| import black | |
| formatted = black.format_str(code, mode=black.FileMode()) | |
| return formatted | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # FILE OPERATIONS | |
| # ============================================================================= | |
| def read_file(file_path: str) -> str: | |
| """Read contents of a file.""" | |
| try: | |
| path = Path(file_path) | |
| if not path.exists(): | |
| return f"Error: File not found: {file_path}" | |
| content = path.read_text(encoding="utf-8", errors="replace") | |
| return _truncate(content) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def write_file(file_path: str, content: str) -> str: | |
| """Write content to a file.""" | |
| try: | |
| path = Path(file_path) | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| path.write_text(content, encoding="utf-8") | |
| return f"File written: {file_path} ({len(content)} chars)" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def list_directory(directory: str = ".") -> str: | |
| """List contents of a directory.""" | |
| try: | |
| path = Path(directory) | |
| if not path.exists(): | |
| return f"Error: Directory not found: {directory}" | |
| items = [] | |
| for item in sorted(path.iterdir()): | |
| item_type = "DIR" if item.is_dir() else "FILE" | |
| size = item.stat().st_size if item.is_file() else "-" | |
| items.append(f"{item_type:4} {size:>12} {item.name}") | |
| return "\n".join(items) if items else "Directory is empty." | |
| except Exception as e: | |
| return _error_msg(e) | |
| def create_directory(directory: str) -> str: | |
| """Create a directory (including parents).""" | |
| try: | |
| Path(directory).mkdir(parents=True, exist_ok=True) | |
| return f"Directory created: {directory}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def delete_file(file_path: str) -> str: | |
| """Delete a file.""" | |
| try: | |
| path = Path(file_path) | |
| if not path.exists(): | |
| return f"Error: File not found: {file_path}" | |
| if path.is_dir(): | |
| shutil.rmtree(path) | |
| return f"Directory deleted: {file_path}" | |
| path.unlink() | |
| return f"File deleted: {file_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def move_file(source: str, destination: str) -> str: | |
| """Move a file or directory.""" | |
| try: | |
| shutil.move(source, destination) | |
| return f"Moved: {source} -> {destination}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def copy_file(source: str, destination: str) -> str: | |
| """Copy a file or directory.""" | |
| try: | |
| src = Path(source) | |
| dst = Path(destination) | |
| if src.is_dir(): | |
| shutil.copytree(src, dst, dirs_exist_ok=True) | |
| else: | |
| dst.parent.mkdir(parents=True, exist_ok=True) | |
| shutil.copy2(src, dst) | |
| return f"Copied: {source} -> {destination}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def file_info(file_path: str) -> str: | |
| """Get detailed information about a file.""" | |
| try: | |
| path = Path(file_path) | |
| if not path.exists(): | |
| return f"Error: File not found: {file_path}" | |
| stat = path.stat() | |
| info = { | |
| "name": path.name, | |
| "absolute_path": str(path.absolute()), | |
| "size_bytes": stat.st_size, | |
| "size_human": _human_readable_size(stat.st_size), | |
| "is_file": path.is_file(), | |
| "is_dir": path.is_dir(), | |
| "is_symlink": path.is_symlink(), | |
| "modified": datetime.datetime.fromtimestamp(stat.st_mtime).isoformat(), | |
| "created": datetime.datetime.fromtimestamp(stat.st_ctime).isoformat(), | |
| "accessed": datetime.datetime.fromtimestamp(stat.st_atime).isoformat(), | |
| "permissions": oct(stat.st_mode)[-3:], | |
| } | |
| return json.dumps(info, indent=2) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def compress_files(files: str, output_path: str = "/tmp/archive.zip") -> str: | |
| """Compress files into a zip archive. files can be comma-separated paths or a directory.""" | |
| try: | |
| paths = [p.strip() for p in files.split(",")] | |
| with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf: | |
| for p in paths: | |
| path = Path(p) | |
| if path.is_dir(): | |
| for file in path.rglob("*"): | |
| if file.is_file(): | |
| zf.write(file, file.relative_to(path.parent)) | |
| elif path.is_file(): | |
| zf.write(path, path.name) | |
| return f"Archive created: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def decompress_archive(archive_path: str, output_dir: str = "/tmp/extracted") -> str: | |
| """Decompress a zip archive.""" | |
| try: | |
| Path(output_dir).mkdir(parents=True, exist_ok=True) | |
| with zipfile.ZipFile(archive_path, "r") as zf: | |
| zf.extractall(output_dir) | |
| return f"Archive extracted to: {output_dir}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # ENCODING TOOLS | |
| # ============================================================================= | |
| def base64_encode(text: str) -> str: | |
| """Encode text to base64.""" | |
| try: | |
| encoded = base64.b64encode(text.encode("utf-8")).decode("utf-8") | |
| return encoded | |
| except Exception as e: | |
| return _error_msg(e) | |
| def base64_decode(text: str) -> str: | |
| """Decode base64 to text.""" | |
| try: | |
| decoded = base64.b64decode(text.encode("utf-8")).decode("utf-8", errors="replace") | |
| return decoded | |
| except Exception as e: | |
| return _error_msg(e) | |
| def hash_data(data: str, algorithm: str = "sha256") -> str: | |
| """Hash data using various algorithms (md5, sha1, sha256, sha512, blake2b).""" | |
| try: | |
| algo = algorithm.lower() | |
| if algo == "md5": | |
| h = hashlib.md5(data.encode("utf-8")) | |
| elif algo == "sha1": | |
| h = hashlib.sha1(data.encode("utf-8")) | |
| elif algo == "sha256": | |
| h = hashlib.sha256(data.encode("utf-8")) | |
| elif algo == "sha512": | |
| h = hashlib.sha512(data.encode("utf-8")) | |
| elif algo == "blake2b": | |
| h = hashlib.blake2b(data.encode("utf-8")) | |
| else: | |
| return f"Error: Unsupported algorithm '{algorithm}'. Use: md5, sha1, sha256, sha512, blake2b" | |
| return f"{algo.upper()}: {h.hexdigest()}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # GENERATOR TOOLS | |
| # ============================================================================= | |
| def generate_password(length: int = 16, use_special: bool = True) -> str: | |
| """Generate a secure random password.""" | |
| try: | |
| length = max(4, min(int(length), 128)) | |
| chars = string.ascii_letters + string.digits | |
| if use_special: | |
| chars += "!@#$%^&*()_+-=[]{}|;:,.<>?" | |
| pwd = "".join(random.SystemRandom().choice(chars) for _ in range(length)) | |
| return pwd | |
| except Exception as e: | |
| return _error_msg(e) | |
| def generate_qr(data: str, output_path: str = "/tmp/qr.png") -> str: | |
| """Generate a QR code image.""" | |
| try: | |
| qr = qrcode.QRCode(version=1, box_size=10, border=4) | |
| qr.add_data(data) | |
| qr.make(fit=True) | |
| img = qr.make_image(fill_color="black", back_color="white") | |
| img.save(output_path) | |
| return f"QR code saved to: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def generate_barcode(data: str, output_path: str = "/tmp/barcode.png") -> str: | |
| """Generate a Code128 barcode image.""" | |
| try: | |
| barcode_obj = Code128(data, writer=ImageWriter()) | |
| barcode_obj.save(output_path.replace(".png", "")) | |
| return f"Barcode saved to: {output_path}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def url_shortener(long_url: str) -> str: | |
| """Shorten a URL using TinyURL.""" | |
| try: | |
| api_url = f"http://tinyurl.com/api-create.php?url={urllib.parse.quote(long_url)}" | |
| resp = requests.get(api_url, timeout=15) | |
| resp.raise_for_status() | |
| return f"Short URL: {resp.text}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def random_number(min_val: int = 0, max_val: int = 100) -> str: | |
| """Generate a random number in a range.""" | |
| try: | |
| result = random.randint(int(min_val), int(max_val)) | |
| return str(result) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def uuid_generator(count: int = 1) -> str: | |
| """Generate UUID(s).""" | |
| try: | |
| count = max(1, min(int(count), 20)) | |
| uuids = [str(uuid.uuid4()) for _ in range(count)] | |
| return "\n".join(uuids) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # NETWORK TOOLS | |
| # ============================================================================= | |
| def dns_lookup(domain: str, record_type: str = "A") -> str: | |
| """Perform DNS lookup for a domain.""" | |
| try: | |
| answers = dns.resolver.resolve(domain, record_type) | |
| results = [str(rdata) for rdata in answers] | |
| return f"{record_type} records for {domain}:\n" + "\n".join(results) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def ip_lookup(ip_address: str = "") -> str: | |
| """Get IP geolocation info from ipapi.co.""" | |
| try: | |
| url = f"https://ipapi.co/{ip_address}/json/" if ip_address else "https://ipapi.co/json/" | |
| resp = requests.get(url, timeout=15) | |
| resp.raise_for_status() | |
| data = resp.json() | |
| if "error" in data: | |
| return f"Error: {data.get('reason', 'Unknown error')}" | |
| lines = [f"{k}: {v}" for k, v in data.items() if v is not None] | |
| return "\n".join(lines) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def whois_lookup(domain: str) -> str: | |
| """Perform WHOIS lookup for a domain.""" | |
| try: | |
| import whois | |
| w = whois.whois(domain) | |
| info = {} | |
| for key in ["domain_name", "registrar", "creation_date", "expiration_date", | |
| "name_servers", "status", "emails", "org", "country"]: | |
| val = getattr(w, key, None) | |
| if val is not None: | |
| info[key] = str(val) | |
| return json.dumps(info, indent=2, default=str) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def ping_host(host: str, count: int = 4) -> str: | |
| """Ping a host.""" | |
| try: | |
| count = min(int(count), 20) | |
| cmd = ["ping", "-c", str(count), host] | |
| result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) | |
| return result.stdout if result.stdout else result.stderr | |
| except Exception as e: | |
| return _error_msg(e) | |
| def port_scan(host: str, ports: str = "80,443,22,21,25,3306,8080") -> str: | |
| """Scan ports on a host.""" | |
| try: | |
| port_list = [int(p.strip()) for p in ports.split(",")] | |
| results = [] | |
| for port in port_list: | |
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| sock.settimeout(2) | |
| result = sock.connect_ex((host, port)) | |
| status = "OPEN" if result == 0 else "CLOSED" | |
| results.append(f"Port {port}: {status}") | |
| sock.close() | |
| return "\n".join(results) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # TEXT PROCESSING TOOLS | |
| # ============================================================================= | |
| def encode_url(text: str) -> str: | |
| """URL-encode a string.""" | |
| try: | |
| return urllib.parse.quote(text) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def decode_url(text: str) -> str: | |
| """URL-decode a string.""" | |
| try: | |
| return urllib.parse.unquote(text) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def html_to_text(html_content: str) -> str: | |
| """Convert HTML to plain text.""" | |
| try: | |
| soup = BeautifulSoup(html_content, "html.parser") | |
| for tag in soup(["script", "style"]): | |
| tag.decompose() | |
| text = soup.get_text(separator="\n", strip=True) | |
| return "\n".join(line.strip() for line in text.splitlines() if line.strip()) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def markdown_to_html(markdown_text: str) -> str: | |
| """Convert Markdown to HTML.""" | |
| try: | |
| import markdown | |
| html_result = markdown.markdown(markdown_text) | |
| return html_result | |
| except Exception as e: | |
| return _error_msg(e) | |
| def json_formatter(json_text: str, indent: int = 2) -> str: | |
| """Format and validate JSON.""" | |
| try: | |
| data = json.loads(json_text) | |
| return json.dumps(data, indent=int(indent), ensure_ascii=False) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def csv_to_json(csv_text: str) -> str: | |
| """Convert CSV text to JSON.""" | |
| try: | |
| import csv | |
| import io | |
| reader = csv.DictReader(io.StringIO(csv_text)) | |
| rows = list(reader) | |
| return json.dumps(rows, indent=2, ensure_ascii=False) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def word_count(text: str) -> str: | |
| """Count words, characters, lines in text.""" | |
| try: | |
| words = len(text.split()) | |
| chars = len(text) | |
| chars_no_space = len(text.replace(" ", "").replace("\n", "")) | |
| lines = len(text.splitlines()) | |
| return ( | |
| f"Words: {words}\n" | |
| f"Characters (with spaces): {chars}\n" | |
| f"Characters (no spaces): {chars_no_space}\n" | |
| f"Lines: {lines}" | |
| ) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def text_diff(text1: str, text2: str) -> str: | |
| """Compare two texts and show differences using difflib.""" | |
| try: | |
| lines1 = text1.splitlines() | |
| lines2 = text2.splitlines() | |
| diff = difflib.unified_diff(lines1, lines2, lineterm="") | |
| result = "\n".join(diff) | |
| return result if result else "No differences found." | |
| except Exception as e: | |
| return _error_msg(e) | |
| def regex_extract(text: str, pattern: str) -> str: | |
| """Extract matches using a regex pattern.""" | |
| try: | |
| matches = re.findall(pattern, text) | |
| if not matches: | |
| return "No matches found." | |
| return "\n".join(str(m) for m in matches) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def regex_replace(text: str, pattern: str, replacement: str = "") -> str: | |
| """Replace text using a regex pattern.""" | |
| try: | |
| result = re.sub(pattern, replacement, text) | |
| return result | |
| except Exception as e: | |
| return _error_msg(e) | |
| def sentiment_analysis(text: str) -> str: | |
| """Analyze sentiment of text using TextBlob.""" | |
| try: | |
| blob = textblob.TextBlob(text) | |
| polarity = blob.sentiment.polarity | |
| subjectivity = blob.sentiment.subjectivity | |
| if polarity > 0.1: | |
| sentiment = "Positive" | |
| elif polarity < -0.1: | |
| sentiment = "Negative" | |
| else: | |
| sentiment = "Neutral" | |
| return ( | |
| f"Sentiment: {sentiment}\n" | |
| f"Polarity: {polarity:.4f} (-1 to +1)\n" | |
| f"Subjectivity: {subjectivity:.4f} (0 to 1)" | |
| ) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def summarize_text(text: str, sentences_count: int = 3) -> str: | |
| """Summarize text using sumy LSA summarizer.""" | |
| try: | |
| sentences_count = max(1, min(int(sentences_count), 20)) | |
| parser = PlaintextParser.from_string(text, Tokenizer("english")) | |
| summarizer = LsaSummarizer() | |
| summary = summarizer(parser.document, sentences_count) | |
| return " ".join(str(s) for s in summary) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def extract_entities(text: str) -> str: | |
| """Extract named entities from text using spaCy.""" | |
| try: | |
| if nlp is None: | |
| return "Error: spaCy model not loaded. Run: python -m spacy download en_core_web_sm" | |
| doc = nlp(text) | |
| entities = [] | |
| for ent in doc.ents: | |
| entities.append(f"{ent.text} ({ent.label_})") | |
| if not entities: | |
| return "No entities found." | |
| return "\n".join(entities) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # CONVERSION TOOLS | |
| # ============================================================================= | |
| def currency_converter(amount: float, from_currency: str = "USD", to_currency: str = "EUR") -> str: | |
| """Convert currency using exchangerate-api.com.""" | |
| try: | |
| url = f"https://api.exchangerate-api.com/v4/latest/{from_currency.upper()}" | |
| resp = requests.get(url, timeout=15) | |
| resp.raise_for_status() | |
| data = resp.json() | |
| rate = data["rates"].get(to_currency.upper()) | |
| if rate is None: | |
| return f"Error: Currency '{to_currency}' not found." | |
| result = float(amount) * rate | |
| return f"{amount} {from_currency.upper()} = {result:.4f} {to_currency.upper()} (rate: {rate})" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def unit_converter(value: float, from_unit: str, to_unit: str) -> str: | |
| """Convert between units using pint.""" | |
| try: | |
| quantity = ureg.Quantity(float(value), from_unit) | |
| result = quantity.to(to_unit) | |
| return f"{value} {from_unit} = {result.magnitude:.6f} {to_unit}" | |
| except Exception as e: | |
| return _error_msg(e) | |
| def timestamp_converter(timestamp: str, to_format: str = "iso") -> str: | |
| """Convert Unix timestamp or ISO string to various formats.""" | |
| try: | |
| try: | |
| ts = float(timestamp) | |
| dt = datetime.datetime.fromtimestamp(ts, tz=datetime.timezone.utc) | |
| except ValueError: | |
| dt = datetime.datetime.fromisoformat(timestamp.replace("Z", "+00:00")) | |
| if to_format.lower() == "iso": | |
| return dt.isoformat() | |
| elif to_format.lower() == "rfc": | |
| return dt.strftime("%a, %d %b %Y %H:%M:%S GMT") | |
| elif to_format.lower() == "date": | |
| return dt.strftime("%Y-%m-%d") | |
| elif to_format.lower() == "time": | |
| return dt.strftime("%H:%M:%S") | |
| elif to_format.lower() == "unix": | |
| return str(int(dt.timestamp())) | |
| else: | |
| return dt.strftime(to_format) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # MEDIA TOOLS | |
| # ============================================================================= | |
| def youtube_transcript(video_url: str, language: str = "en") -> str: | |
| """Get transcript from a YouTube video.""" | |
| try: | |
| patterns = [ | |
| r"v=([a-zA-Z0-9_-]{11})", | |
| r"youtu\.be/([a-zA-Z0-9_-]{11})", | |
| r"shorts/([a-zA-Z0-9_-]{11})", | |
| ] | |
| video_id = None | |
| for p in patterns: | |
| m = re.search(p, video_url) | |
| if m: | |
| video_id = m.group(1) | |
| break | |
| if not video_id: | |
| return "Error: Could not extract YouTube video ID from URL." | |
| transcript_list = YouTubeTranscriptApi.get_transcript(video_id, languages=[language]) | |
| lines = [f"[{t['start']:.1f}s] {t['text']}" for t in transcript_list] | |
| return _truncate("\n".join(lines)) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def extract_links(text: str) -> str: | |
| """Extract URLs from text.""" | |
| try: | |
| pattern = r"https?://[^\s<>"{}|\^`\[\]]+" | |
| matches = re.findall(pattern, text) | |
| if not matches: | |
| return "No links found." | |
| return "\n".join(matches) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def extract_emails(text: str) -> str: | |
| """Extract email addresses from text.""" | |
| try: | |
| pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" | |
| matches = re.findall(pattern, text) | |
| if not matches: | |
| return "No emails found." | |
| return "\n".join(set(matches)) | |
| except Exception as e: | |
| return _error_msg(e) | |
| def extract_phones(text: str) -> str: | |
| """Extract phone numbers from text.""" | |
| try: | |
| pattern = r"(?:\+?1[-.\s]?)?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}" | |
| matches = re.findall(pattern, text) | |
| if not matches: | |
| return "No phone numbers found." | |
| return "\n".join(set(matches)) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # SYSTEM TOOLS | |
| # ============================================================================= | |
| def git_status(repo_path: str = ".") -> str: | |
| """Get git status of a repository.""" | |
| try: | |
| result = subprocess.run( | |
| ["git", "-C", repo_path, "status", "-sb"], | |
| capture_output=True, text=True, timeout=15 | |
| ) | |
| return result.stdout if result.stdout else result.stderr | |
| except Exception as e: | |
| return _error_msg(e) | |
| def git_log(repo_path: str = ".", count: int = 10) -> str: | |
| """Get git log of a repository.""" | |
| try: | |
| count = min(int(count), 50) | |
| result = subprocess.run( | |
| ["git", "-C", repo_path, "log", f"--max-count={count}", "--oneline", "--decorate"], | |
| capture_output=True, text=True, timeout=15 | |
| ) | |
| return result.stdout if result.stdout else result.stderr | |
| except Exception as e: | |
| return _error_msg(e) | |
| def system_info() -> str: | |
| """Get system information using platform and psutil.""" | |
| try: | |
| info = { | |
| "platform": platform.platform(), | |
| "system": platform.system(), | |
| "release": platform.release(), | |
| "version": platform.version(), | |
| "machine": platform.machine(), | |
| "processor": platform.processor(), | |
| "hostname": platform.node(), | |
| "python_version": platform.python_version(), | |
| "cpu_count": psutil.cpu_count(), | |
| "cpu_percent": psutil.cpu_percent(interval=1), | |
| "memory_total_gb": round(psutil.virtual_memory().total / (1024**3), 2), | |
| "memory_available_gb": round(psutil.virtual_memory().available / (1024**3), 2), | |
| "memory_percent": psutil.virtual_memory().percent, | |
| "disk_usage_percent": psutil.disk_usage("/").percent, | |
| "boot_time": datetime.datetime.fromtimestamp(psutil.boot_time()).isoformat(), | |
| } | |
| return json.dumps(info, indent=2) | |
| except Exception as e: | |
| return _error_msg(e) | |
| # ============================================================================= | |
| # TOOL_MAP | |
| # ============================================================================= | |
| TOOL_MAP = { | |
| # Web | |
| "web_search": web_search, | |
| "browse_page": browse_page, | |
| "playwright_screenshot": playwright_screenshot, | |
| "playwright_pdf": playwright_pdf, | |
| # Documents | |
| "create_pdf": create_pdf, | |
| "create_docx": create_docx, | |
| # Images | |
| "describe_image": describe_image, | |
| "ocr_image": ocr_image, | |
| # Translation | |
| "translate_text": translate_text, | |
| # Data | |
| "get_weather": get_weather, | |
| "get_news": get_news, | |
| "get_stock_price": get_stock_price, | |
| # Math/Code | |
| "calculator": calculator, | |
| "python_interpreter": python_interpreter, | |
| "execute_command": execute_command, | |
| "code_formatter": code_formatter, | |
| # File Ops | |
| "read_file": read_file, | |
| "write_file": write_file, | |
| "list_directory": list_directory, | |
| "create_directory": create_directory, | |
| "delete_file": delete_file, | |
| "move_file": move_file, | |
| "copy_file": copy_file, | |
| "file_info": file_info, | |
| "compress_files": compress_files, | |
| "decompress_archive": decompress_archive, | |
| # Encoding | |
| "base64_encode": base64_encode, | |
| "base64_decode": base64_decode, | |
| "hash_data": hash_data, | |
| # Generators | |
| "generate_password": generate_password, | |
| "generate_qr": generate_qr, | |
| "generate_barcode": generate_barcode, | |
| "url_shortener": url_shortener, | |
| "random_number": random_number, | |
| "uuid_generator": uuid_generator, | |
| # Network | |
| "dns_lookup": dns_lookup, | |
| "ip_lookup": ip_lookup, | |
| "whois_lookup": whois_lookup, | |
| "ping_host": ping_host, | |
| "port_scan": port_scan, | |
| # Text Processing | |
| "encode_url": encode_url, | |
| "decode_url": decode_url, | |
| "html_to_text": html_to_text, | |
| "markdown_to_html": markdown_to_html, | |
| "json_formatter": json_formatter, | |
| "csv_to_json": csv_to_json, | |
| "word_count": word_count, | |
| "text_diff": text_diff, | |
| "regex_extract": regex_extract, | |
| "regex_replace": regex_replace, | |
| "sentiment_analysis": sentiment_analysis, | |
| "summarize_text": summarize_text, | |
| "extract_entities": extract_entities, | |
| # Conversion | |
| "currency_converter": currency_converter, | |
| "unit_converter": unit_converter, | |
| "timestamp_converter": timestamp_converter, | |
| # Media | |
| "youtube_transcript": youtube_transcript, | |
| "extract_links": extract_links, | |
| "extract_emails": extract_emails, | |
| "extract_phones": extract_phones, | |
| # System | |
| "git_status": git_status, | |
| "git_log": git_log, | |
| "system_info": system_info, | |
| } | |
| # ============================================================================= | |
| # TOOL_DEFINITIONS (OpenAI format) | |
| # ============================================================================= | |
| TOOL_DEFINITIONS = [ | |
| # ===================== WEB ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "web_search", | |
| "description": "Search the web using DuckDuckGo and return search results with titles, URLs, and snippets.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "query": {"type": "string", "description": "Search query string"}, | |
| "max_results": {"type": "integer", "description": "Maximum number of results (1-10)", "default": 5} | |
| }, | |
| "required": ["query"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "browse_page", | |
| "description": "Fetch and extract clean text content from a web page using requests and BeautifulSoup.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "url": {"type": "string", "description": "URL of the page to browse"} | |
| }, | |
| "required": ["url"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "playwright_screenshot", | |
| "description": "Take a full-page screenshot of a webpage using Playwright and save as PNG.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "url": {"type": "string", "description": "URL to screenshot"}, | |
| "output_path": {"type": "string", "description": "Path to save the screenshot", "default": "/tmp/screenshot.png"} | |
| }, | |
| "required": ["url"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "playwright_pdf", | |
| "description": "Save a webpage as a PDF using Playwright.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "url": {"type": "string", "description": "URL to convert to PDF"}, | |
| "output_path": {"type": "string", "description": "Path to save the PDF", "default": "/tmp/page.pdf"} | |
| }, | |
| "required": ["url"] | |
| } | |
| } | |
| }, | |
| # ===================== DOCUMENTS ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "create_pdf", | |
| "description": "Create a PDF file from text content using ReportLab.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "content": {"type": "string", "description": "Text content for the PDF"}, | |
| "output_path": {"type": "string", "description": "Output file path", "default": "/tmp/output.pdf"}, | |
| "title": {"type": "string", "description": "PDF title", "default": "Document"} | |
| }, | |
| "required": ["content"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "create_docx", | |
| "description": "Create a DOCX file from text content using python-docx.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "content": {"type": "string", "description": "Text content for the document"}, | |
| "output_path": {"type": "string", "description": "Output file path", "default": "/tmp/output.docx"}, | |
| "title": {"type": "string", "description": "Document title", "default": "Document"} | |
| }, | |
| "required": ["content"] | |
| } | |
| } | |
| }, | |
| # ===================== IMAGES ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "describe_image", | |
| "description": "Describe an image using Gemini Vision API. Requires GEMINI_API_KEY.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "image_path": {"type": "string", "description": "Path to the image file"}, | |
| "prompt": {"type": "string", "description": "Custom prompt for description", "default": "Describe this image in detail."} | |
| }, | |
| "required": ["image_path"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "ocr_image", | |
| "description": "Extract text from an image using pytesseract OCR.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "image_path": {"type": "string", "description": "Path to the image file"}, | |
| "language": {"type": "string", "description": "OCR language code", "default": "eng"} | |
| }, | |
| "required": ["image_path"] | |
| } | |
| } | |
| }, | |
| # ===================== TRANSLATION ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "translate_text", | |
| "description": "Translate text using Google Translate via deep_translator.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to translate"}, | |
| "target_language": {"type": "string", "description": "Target language code (e.g., en, es, fr, de, ja)", "default": "en"}, | |
| "source_language": {"type": "string", "description": "Source language code or 'auto'", "default": "auto"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| # ===================== DATA ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_weather", | |
| "description": "Get current weather information for a location using wttr.in.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "location": {"type": "string", "description": "City name or location"} | |
| }, | |
| "required": ["location"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_news", | |
| "description": "Get latest news using DuckDuckGo news search.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "query": {"type": "string", "description": "News search query", "default": "latest news"}, | |
| "max_results": {"type": "integer", "description": "Maximum results (1-10)", "default": 5} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_stock_price", | |
| "description": "Get stock price and info using yfinance.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "ticker": {"type": "string", "description": "Stock ticker symbol (e.g., AAPL, TSLA, GOOGL)"} | |
| }, | |
| "required": ["ticker"] | |
| } | |
| } | |
| }, | |
| # ===================== MATH/CODE ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "calculator", | |
| "description": "Evaluate a mathematical expression safely using math functions.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "expression": {"type": "string", "description": "Mathematical expression to evaluate (e.g., 'sin(pi/2) + sqrt(16)')"} | |
| }, | |
| "required": ["expression"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "python_interpreter", | |
| "description": "Execute Python code safely and return the result.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "code": {"type": "string", "description": "Python code to execute"} | |
| }, | |
| "required": ["code"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "execute_command", | |
| "description": "Execute a shell command safely with timeout.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "command": {"type": "string", "description": "Shell command to execute"}, | |
| "timeout": {"type": "integer", "description": "Timeout in seconds", "default": 30} | |
| }, | |
| "required": ["command"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "code_formatter", | |
| "description": "Format Python code using black.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "code": {"type": "string", "description": "Python code to format"}, | |
| "language": {"type": "string", "description": "Programming language (only 'python' supported)", "default": "python"} | |
| }, | |
| "required": ["code"] | |
| } | |
| } | |
| }, | |
| # ===================== FILE OPS ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "read_file", | |
| "description": "Read the contents of a file.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "file_path": {"type": "string", "description": "Path to the file"} | |
| }, | |
| "required": ["file_path"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "write_file", | |
| "description": "Write content to a file (creates directories if needed).", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "file_path": {"type": "string", "description": "Path to write the file"}, | |
| "content": {"type": "string", "description": "Content to write"} | |
| }, | |
| "required": ["file_path", "content"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "list_directory", | |
| "description": "List files and directories in a path.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "directory": {"type": "string", "description": "Directory path", "default": "."} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "create_directory", | |
| "description": "Create a directory (including parent directories).", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "directory": {"type": "string", "description": "Directory path to create"} | |
| }, | |
| "required": ["directory"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "delete_file", | |
| "description": "Delete a file or directory.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "file_path": {"type": "string", "description": "Path to delete"} | |
| }, | |
| "required": ["file_path"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "move_file", | |
| "description": "Move a file or directory to a new location.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "source": {"type": "string", "description": "Source path"}, | |
| "destination": {"type": "string", "description": "Destination path"} | |
| }, | |
| "required": ["source", "destination"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "copy_file", | |
| "description": "Copy a file or directory.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "source": {"type": "string", "description": "Source path"}, | |
| "destination": {"type": "string", "description": "Destination path"} | |
| }, | |
| "required": ["source", "destination"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "file_info", | |
| "description": "Get detailed information about a file (size, dates, permissions).", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "file_path": {"type": "string", "description": "Path to the file"} | |
| }, | |
| "required": ["file_path"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "compress_files", | |
| "description": "Compress files or directories into a zip archive.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "files": {"type": "string", "description": "Comma-separated file/directory paths"}, | |
| "output_path": {"type": "string", "description": "Output zip file path", "default": "/tmp/archive.zip"} | |
| }, | |
| "required": ["files"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "decompress_archive", | |
| "description": "Extract a zip archive to a directory.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "archive_path": {"type": "string", "description": "Path to the zip archive"}, | |
| "output_dir": {"type": "string", "description": "Directory to extract to", "default": "/tmp/extracted"} | |
| }, | |
| "required": ["archive_path"] | |
| } | |
| } | |
| }, | |
| # ===================== ENCODING ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "base64_encode", | |
| "description": "Encode text to base64.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to encode"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "base64_decode", | |
| "description": "Decode base64 to text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Base64 string to decode"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "hash_data", | |
| "description": "Hash data using md5, sha1, sha256, sha512, or blake2b.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "data": {"type": "string", "description": "Data to hash"}, | |
| "algorithm": {"type": "string", "description": "Hash algorithm", "default": "sha256", "enum": ["md5", "sha1", "sha256", "sha512", "blake2b"]} | |
| }, | |
| "required": ["data"] | |
| } | |
| } | |
| }, | |
| # ===================== GENERATORS ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "generate_password", | |
| "description": "Generate a secure random password.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "length": {"type": "integer", "description": "Password length (4-128)", "default": 16}, | |
| "use_special": {"type": "boolean", "description": "Include special characters", "default": True} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "generate_qr", | |
| "description": "Generate a QR code image.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "data": {"type": "string", "description": "Data to encode in QR code"}, | |
| "output_path": {"type": "string", "description": "Output image path", "default": "/tmp/qr.png"} | |
| }, | |
| "required": ["data"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "generate_barcode", | |
| "description": "Generate a Code128 barcode image.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "data": {"type": "string", "description": "Data to encode in barcode"}, | |
| "output_path": {"type": "string", "description": "Output image path", "default": "/tmp/barcode.png"} | |
| }, | |
| "required": ["data"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "url_shortener", | |
| "description": "Shorten a URL using TinyURL.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "long_url": {"type": "string", "description": "URL to shorten"} | |
| }, | |
| "required": ["long_url"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "random_number", | |
| "description": "Generate a random integer in a range.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "min_val": {"type": "integer", "description": "Minimum value", "default": 0}, | |
| "max_val": {"type": "integer", "description": "Maximum value", "default": 100} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "uuid_generator", | |
| "description": "Generate one or more UUID v4 strings.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "count": {"type": "integer", "description": "Number of UUIDs (1-20)", "default": 1} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| # ===================== NETWORK ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "dns_lookup", | |
| "description": "Perform DNS lookup for a domain.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "domain": {"type": "string", "description": "Domain to lookup"}, | |
| "record_type": {"type": "string", "description": "DNS record type", "default": "A", "enum": ["A", "AAAA", "MX", "TXT", "NS", "CNAME", "SOA"]} | |
| }, | |
| "required": ["domain"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "ip_lookup", | |
| "description": "Get IP geolocation information from ipapi.co.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "ip_address": {"type": "string", "description": "IP address (empty for own IP)", "default": ""} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "whois_lookup", | |
| "description": "Perform WHOIS lookup for a domain.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "domain": {"type": "string", "description": "Domain to lookup"} | |
| }, | |
| "required": ["domain"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "ping_host", | |
| "description": "Ping a host and return results.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "host": {"type": "string", "description": "Host to ping"}, | |
| "count": {"type": "integer", "description": "Number of pings", "default": 4} | |
| }, | |
| "required": ["host"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "port_scan", | |
| "description": "Scan ports on a host.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "host": {"type": "string", "description": "Host to scan"}, | |
| "ports": {"type": "string", "description": "Comma-separated port numbers", "default": "80,443,22,21,25,3306,8080"} | |
| }, | |
| "required": ["host"] | |
| } | |
| } | |
| }, | |
| # ===================== TEXT PROCESSING ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "encode_url", | |
| "description": "URL-encode a string.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to encode"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "decode_url", | |
| "description": "URL-decode a string.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to decode"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "html_to_text", | |
| "description": "Convert HTML content to plain text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "html_content": {"type": "string", "description": "HTML content to convert"} | |
| }, | |
| "required": ["html_content"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "markdown_to_html", | |
| "description": "Convert Markdown text to HTML.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "markdown_text": {"type": "string", "description": "Markdown text to convert"} | |
| }, | |
| "required": ["markdown_text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "json_formatter", | |
| "description": "Format and validate JSON text with indentation.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "json_text": {"type": "string", "description": "JSON string to format"}, | |
| "indent": {"type": "integer", "description": "Indentation spaces", "default": 2} | |
| }, | |
| "required": ["json_text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "csv_to_json", | |
| "description": "Convert CSV text to JSON.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "csv_text": {"type": "string", "description": "CSV text to convert"} | |
| }, | |
| "required": ["csv_text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "word_count", | |
| "description": "Count words, characters, and lines in text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to analyze"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "text_diff", | |
| "description": "Compare two texts and show differences using unified diff format.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text1": {"type": "string", "description": "First text"}, | |
| "text2": {"type": "string", "description": "Second text"} | |
| }, | |
| "required": ["text1", "text2"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "regex_extract", | |
| "description": "Extract all matches of a regex pattern from text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to search"}, | |
| "pattern": {"type": "string", "description": "Regex pattern"} | |
| }, | |
| "required": ["text", "pattern"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "regex_replace", | |
| "description": "Replace text using a regex pattern.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to modify"}, | |
| "pattern": {"type": "string", "description": "Regex pattern to match"}, | |
| "replacement": {"type": "string", "description": "Replacement string", "default": ""} | |
| }, | |
| "required": ["text", "pattern"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "sentiment_analysis", | |
| "description": "Analyze sentiment of text using TextBlob.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to analyze"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "summarize_text", | |
| "description": "Summarize text using LSA summarizer.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to summarize"}, | |
| "sentences_count": {"type": "integer", "description": "Number of sentences in summary", "default": 3} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "extract_entities", | |
| "description": "Extract named entities from text using spaCy.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to analyze"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| # ===================== CONVERSION ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "currency_converter", | |
| "description": "Convert currency using exchangerate-api.com.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "amount": {"type": "number", "description": "Amount to convert"}, | |
| "from_currency": {"type": "string", "description": "Source currency code", "default": "USD"}, | |
| "to_currency": {"type": "string", "description": "Target currency code", "default": "EUR"} | |
| }, | |
| "required": ["amount"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "unit_converter", | |
| "description": "Convert between units using pint (e.g., meters to feet, kg to lbs).", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "value": {"type": "number", "description": "Value to convert"}, | |
| "from_unit": {"type": "string", "description": "Source unit (e.g., meter, kg, celsius)"}, | |
| "to_unit": {"type": "string", "description": "Target unit (e.g., foot, lb, fahrenheit)"} | |
| }, | |
| "required": ["value", "from_unit", "to_unit"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "timestamp_converter", | |
| "description": "Convert between Unix timestamps and human-readable formats.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "timestamp": {"type": "string", "description": "Unix timestamp or ISO datetime string"}, | |
| "to_format": {"type": "string", "description": "Output format: iso, rfc, date, time, unix, or custom strftime", "default": "iso"} | |
| }, | |
| "required": ["timestamp"] | |
| } | |
| } | |
| }, | |
| # ===================== MEDIA ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "youtube_transcript", | |
| "description": "Get transcript from a YouTube video URL.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "video_url": {"type": "string", "description": "YouTube video URL"}, | |
| "language": {"type": "string", "description": "Transcript language code", "default": "en"} | |
| }, | |
| "required": ["video_url"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "extract_links", | |
| "description": "Extract all URLs from text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to extract links from"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "extract_emails", | |
| "description": "Extract all email addresses from text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to extract emails from"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "extract_phones", | |
| "description": "Extract phone numbers from text.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "text": {"type": "string", "description": "Text to extract phone numbers from"} | |
| }, | |
| "required": ["text"] | |
| } | |
| } | |
| }, | |
| # ===================== SYSTEM ===================== | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "git_status", | |
| "description": "Get git status of a repository.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "repo_path": {"type": "string", "description": "Path to git repository", "default": "."} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "git_log", | |
| "description": "Get git commit history of a repository.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "repo_path": {"type": "string", "description": "Path to git repository", "default": "."}, | |
| "count": {"type": "integer", "description": "Number of commits (max 50)", "default": 10} | |
| }, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "system_info", | |
| "description": "Get system information including CPU, memory, disk, and platform details.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": {}, | |
| "required": [] | |
| } | |
| } | |
| }, | |
| ] | |