From 6c33951c813f55dcb72b0dbbf5f0eb92653c69c6 Mon Sep 17 00:00:00 2001 From: moosecrap Date: Tue, 22 Sep 2026 12:53:29 -0700 Subject: [PATCH] Symbolic link handling --- tools/list_directory.py | 13 +++++++++++-- tools/utils.py | 25 +++++++++++++++++-------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/tools/list_directory.py b/tools/list_directory.py index 8fb1943..5986c2c 100644 --- a/tools/list_directory.py +++ b/tools/list_directory.py @@ -48,16 +48,25 @@ async def handle(args: Dict[str, Any]): output = [] for item in paged_items: mtime_rel = format_relative_time(item["mtime"]) + + # Handle symbolic links in the display name + display_name = item["name"] + if item.get("is_link"): + target = item["target"] + is_broken = not item["path"].exists() + broken_str = " (BROKEN)" if is_broken else "" + display_name = f"{item['name']} -> {target}{broken_str}" + if item["is_dir"]: try: count = len(list(item["path"].iterdir())) info = f"{count} items" except: info = "0 items" - output.append(f"[DIR] {item['name']} | {info} | {mtime_rel}") + output.append(f"[DIR] {display_name} | {info} | {mtime_rel}") else: size_kb = item["size"] / 1024 - output.append(f" {item['name']} | {size_kb:.1f}KB | {mtime_rel}") + output.append(f" {display_name} | {size_kb:.1f}KB | {mtime_rel}") header = f"Listing of {path}\nPage {effective_page} of {total_pages} ({total_items} total items). Showing {start_idx+1}-{min(end_idx, total_items)}." diff --git a/tools/utils.py b/tools/utils.py index 411f427..14be389 100644 --- a/tools/utils.py +++ b/tools/utils.py @@ -61,14 +61,23 @@ def get_file_info_list(path: Path, extensions: Optional[tuple] = None) -> List[D if extensions and not entry.name.lower().endswith(extensions): continue - stats = entry.stat() - items.append({ - "name": entry.name, - "path": entry, - "mtime": stats.st_mtime, - "size": stats.st_size, - "is_dir": entry.is_dir() - }) + try: + stats = entry.lstat() + is_link = entry.is_symlink() + target = str(entry.readlink()) if is_link else None + + items.append({ + "name": entry.name, + "path": entry, + "mtime": stats.st_mtime, + "size": stats.st_size, + "is_dir": entry.is_dir(), + "is_link": is_link, + "target": target + }) + except Exception: + # Skip items that are completely inaccessible + continue except Exception as e: raise ToolError(f"Error accessing directory {path}: {e}")