#!/usr/bin/env python3 """Read a file from /workspace with optional line range.""" import json import os import sys args = json.loads(sys.stdin.read()) path = args.get("path", "") offset = max(int(args.get("offset", 1)), 1) limit = max(int(args.get("limit", 200)), 1) WORKSPACE = os.environ.get("WORKSPACE", "/workspace") # Resolve to absolute and ensure it stays under /workspace resolved = os.path.realpath(path) if not resolved.startswith(WORKSPACE + "/") and resolved != WORKSPACE: print(f"[error: path must be under {WORKSPACE}]") sys.exit(0) if not os.path.exists(resolved): print(f"[error: file not found: {path}]") sys.exit(0) if os.path.isdir(resolved): entries = sorted(os.listdir(resolved)) print(f"Directory listing of {path} ({len(entries)} entries):") for entry in entries[:100]: full = os.path.join(resolved, entry) kind = "dir" if os.path.isdir(full) else "file" print(f" {entry} ({kind})") if len(entries) > 100: print(f" ... and {len(entries) - 100} more") sys.exit(0) # Binary detection — check first 512 bytes try: with open(resolved, "rb") as f: chunk = f.read(512) if b"\x00" in chunk: size = os.path.getsize(resolved) print(f"[binary file: {path} ({size} bytes)]") sys.exit(0) except Exception as e: print(f"[error reading file: {e}]") sys.exit(0) # Read with line range try: with open(resolved) as f: lines = f.readlines() except Exception as e: print(f"[error reading file: {e}]") sys.exit(0) total = len(lines) start_idx = offset - 1 # 0-based end_idx = min(start_idx + limit, total) if start_idx >= total: print(f"[file has {total} lines — offset {offset} is beyond end of file]") sys.exit(0) for i in range(start_idx, end_idx): print(f"{i + 1}\t{lines[i]}", end="") if end_idx < total: print(f"\n[showing lines {offset}-{end_idx} of {total} — use offset={end_idx + 1} to read more]")