This commit is contained in:
moosecrap 2026-07-21 03:44:42 -07:00
parent 30d6453c6b
commit f0ad4d0d35

View File

@ -61,6 +61,7 @@ async def list_thumbnails_handler(args: Dict[str, Any]):
dir_path = args.get("path")
page = int(args.get("page", 1))
page_size = int(args.get("page_size", 64))
sort_by = args.get("sort_by", "mtime")
if not dir_path:
return {"text": "Error: Missing path argument"}
@ -68,24 +69,47 @@ async def list_thumbnails_handler(args: Dict[str, Any]):
return {"text": f"Error: {dir_path} is not a directory."}
exts = ('.png', '.jpg', '.jpeg', '.webp', '.bmp')
all_files = sorted([f for f in os.listdir(dir_path) if f.lower().endswith(exts)])
if not all_files:
# Collect file info for sorting
file_info_list = []
for f in os.listdir(dir_path):
if f.lower().endswith(exts):
full_path = os.path.join(dir_path, f)
try:
stats = os.stat(full_path)
file_info_list.append({
"name": f,
"path": full_path,
"mtime": stats.st_mtime,
"size": stats.st_size
})
except Exception as e:
logger.error(f"Could not stat {f}: {e}")
if not file_info_list:
return {"text": "No supported images found in the directory."}
total_files = len(all_files)
# Sorting logic
if sort_by == "mtime":
file_info_list.sort(key=lambda x: x["mtime"], reverse=True)
elif sort_by == "size":
file_info_list.sort(key=lambda x: x["size"], reverse=True)
else: # Default to name
file_info_list.sort(key=lambda x: x["name"].lower())
total_files = len(file_info_list)
start_idx = (page - 1) * page_size
end_idx = start_idx + page_size
files = all_files[start_idx:end_idx]
paged_files = file_info_list[start_idx:end_idx]
if not files:
if not paged_files:
return {"text": f"No images found on page {page}."}
thumb_size = 160
padding = 15
label_height = 30
label_height = 35 # Increased for larger font
num_files = len(files)
num_files = len(paged_files)
cols = int(num_files**0.5) if num_files > 0 else 1
if cols == 0: cols = 1
rows = (num_files + cols - 1) // cols
@ -96,38 +120,53 @@ async def list_thumbnails_handler(args: Dict[str, Any]):
canvas = Image.new('RGB', (canvas_w, canvas_h), (30, 30, 30))
draw = ImageDraw.Draw(canvas)
try:
# Attempt to load a larger font
font = None
font_paths = [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
"/usr/share/fonts/truetype/freefont/FreeSansBold.ttf",
]
for path in font_paths:
if os.path.exists(path):
try:
font = ImageFont.truetype(path, 20)
break
except Exception:
continue
if font is None:
font = ImageFont.load_default()
except Exception:
font = None
file_details = []
for i, filename in enumerate(files):
full_path = os.path.join(dir_path, filename)
for i, info in enumerate(paged_files):
filename = info["name"]
full_path = info["path"]
row = i // cols
col = i % cols
x = padding + col * (thumb_size + padding)
y = padding + row * (thumb_size + label_height + padding)
# Gather metadata for the text list
try:
stats = os.stat(full_path)
with Image.open(full_path) as img:
width, height = img.size
# Process thumbnail
img.thumbnail((thumb_size, thumb_size))
off_x = (thumb_size - img.width) // 2
off_y = (thumb_size - img.height) // 2
canvas.paste(img, (x + off_x, y + off_y))
mod_time = datetime.datetime.fromtimestamp(stats.st_mtime).strftime('%Y-%m-%d %H:%M')
size_kb = stats.st_size / 1024
mod_time = datetime.datetime.fromtimestamp(info["mtime"]).strftime('%Y-%m-%d %H:%M')
size_kb = info["size"] / 1024
file_details.append(f"{i+1}. {filename} | {width}x{height} | {size_kb:.1f}KB | {mod_time}")
# Label the thumbnail with just the index number
draw.text((x, y + thumb_size + 2), str(i + 1), fill=(220, 220, 220), font=font)
# Draw index number - add a small background rectangle for contrast
text = str(i + 1)
# Simple text bounding box calculation (approximate)
text_w = len(text) * 10
draw.rectangle([x, y + thumb_size + 2, x + text_w + 4, y + thumb_size + 24], fill=(60, 60, 60))
draw.text((x + 2, y + thumb_size + 2), text, fill=(255, 255, 255), font=font)
except Exception as e:
logger.error(f"Failed to process {filename}: {e}")
draw.text((x, y + thumb_size // 2), "Error", fill=(255, 0, 0), font=font)
@ -170,13 +209,14 @@ TOOL_REGISTRY = [
),
Tool(
name="list_thumbnails",
description="Generates a thumbnail grid of images in a directory. Returns a numbered grid and a detailed file list.",
description="Generates a thumbnail grid of images in a directory. Supports pagination and sorting.",
schema={
"type": "object",
"properties": {
"path": {"type": "string", "description": "Path to the directory containing images"},
"page": {"type": "integer", "description": "The page number to retrieve (1-indexed)", "default": 1},
"page_size": {"type": "integer", "description": "Number of images per page", "default": 64},
"sort_by": {"type": "string", "description": "Sort order: 'mtime' (newest first, default), 'name' (alphabetical), or 'size' (largest first)", "default": "mtime"},
},
"required": ["path"],
},