Victor Dibia b89ca2a5ae
Fix warnings in AGS (#5320)
This PR does the following: 

- Fix warning messages in AGS on launch.
- Improve Cli message to include app URL on startup from command line
- Minor improvements default gallery generator. (add more default tools)
- Improve new session behaviour.



## Related issue number

Closes #5097

## Checks
2025-02-04 06:32:34 +00:00

129 lines
4.2 KiB
Python

import unicodedata
import uuid
from io import BytesIO
from pathlib import Path
from typing import Dict, List, Optional
import requests
from autogen_core.code_executor import ImportFromModule
from autogen_core.tools import FunctionTool
from fpdf import FPDF
from PIL import Image, ImageDraw, ImageOps
async def generate_pdf(
sections: List[Dict[str, Optional[str]]], output_file: str = "report.pdf", report_title: str = "PDF Report"
) -> str:
"""
Generate a PDF report with formatted sections including text and images.
Args:
sections: List of dictionaries containing section details with keys:
- title: Section title
- level: Heading level (title, h1, h2)
- content: Section text content
- image: Optional image URL or file path
output_file: Name of output PDF file
report_title: Title shown at top of report
Returns:
str: Path to the generated PDF file
"""
def normalize_text(text: str) -> str:
"""Normalize Unicode text to ASCII."""
return unicodedata.normalize("NFKD", text).encode("ascii", "ignore").decode("ascii")
def get_image(image_url_or_path):
"""Fetch image from URL or local path."""
if image_url_or_path.startswith(("http://", "https://")):
response = requests.get(image_url_or_path)
if response.status_code == 200:
return BytesIO(response.content)
elif Path(image_url_or_path).is_file():
return open(image_url_or_path, "rb")
return None
def add_rounded_corners(img, radius=6):
"""Add rounded corners to an image."""
mask = Image.new("L", img.size, 0)
draw = ImageDraw.Draw(mask)
draw.rounded_rectangle([(0, 0), img.size], radius, fill=255)
img = ImageOps.fit(img, mask.size, centering=(0.5, 0.5))
img.putalpha(mask)
return img
class PDF(FPDF):
"""Custom PDF class with header and content formatting."""
def header(self):
self.set_font("Arial", "B", 12)
normalized_title = normalize_text(report_title)
self.cell(0, 10, normalized_title, 0, 1, "C")
def chapter_title(self, txt):
self.set_font("Arial", "B", 12)
normalized_txt = normalize_text(txt)
self.cell(0, 10, normalized_txt, 0, 1, "L")
self.ln(2)
def chapter_body(self, body):
self.set_font("Arial", "", 12)
normalized_body = normalize_text(body)
self.multi_cell(0, 10, normalized_body)
self.ln()
def add_image(self, img_data):
img = Image.open(img_data)
img = add_rounded_corners(img)
img_path = Path(f"temp_{uuid.uuid4().hex}.png")
img.save(img_path, format="PNG")
self.image(str(img_path), x=None, y=None, w=190 if img.width > 190 else img.width)
self.ln(10)
img_path.unlink()
# Initialize PDF
pdf = PDF()
pdf.add_page()
font_size = {"title": 16, "h1": 14, "h2": 12, "body": 12}
# Add sections
for section in sections:
title = section.get("title", "")
level = section.get("level", "h1")
content = section.get("content", "")
image = section.get("image")
pdf.set_font("Arial", "B" if level in font_size else "", font_size.get(level, font_size["body"]))
pdf.chapter_title(title)
if content:
pdf.chapter_body(content)
if image:
img_data = get_image(image)
if img_data:
pdf.add_image(img_data)
if isinstance(img_data, BytesIO):
img_data.close()
pdf.output(output_file)
return output_file
# Create the PDF generation tool
generate_pdf_tool = FunctionTool(
func=generate_pdf,
description="Generate PDF reports with formatted sections containing text and images",
global_imports=[
"uuid",
"requests",
"unicodedata",
ImportFromModule("typing", ("List", "Dict", "Optional")),
ImportFromModule("pathlib", ("Path",)),
ImportFromModule("fpdf", ("FPDF",)),
ImportFromModule("PIL", ("Image", "ImageDraw", "ImageOps")),
ImportFromModule("io", ("BytesIO",)),
],
)