Deskaid

  • codemcp
#!/usr/bin/env python3 import os # Constants MAX_LINES_TO_READ = 1000 MAX_LINE_LENGTH = 1000 MAX_OUTPUT_SIZE = 0.25 * 1024 * 1024 # 0.25MB in bytes START_CONTEXT_LINES = 5 # Number of lines to keep from the beginning when truncating __all__ = [ "MAX_LINES_TO_READ", "MAX_LINE_LENGTH", "MAX_OUTPUT_SIZE", "START_CONTEXT_LINES", "is_image_file", "get_image_format", "normalize_file_path", "get_edit_snippet", "truncate_output_content", ] def is_image_file(file_path: str) -> bool: """Check if a file is an image based on its MIME type.""" # Stub implementation - we don't care about image support return False def get_image_format(file_path: str) -> str: """Get the format of an image file.""" # Stub implementation - we don't care about image support return "png" def normalize_file_path(file_path: str) -> str: """Normalize a file path to an absolute path.""" if not os.path.isabs(file_path): return os.path.abspath(os.path.join(os.getcwd(), file_path)) return os.path.abspath(file_path) def get_edit_snippet( original_text: str, old_str: str, new_str: str, context_lines: int = 4, ) -> str: """Generate a snippet of the edited file showing the changes with line numbers. Args: original_text: The original file content old_str: The text that was replaced new_str: The new text that replaced old_str context_lines: Number of lines to show before and after the change Returns: A formatted string with line numbers and the edited content """ # Find where the edit occurs before_text = original_text.split(old_str)[0] before_lines = before_text.split("\n") replacement_line = len(before_lines) # Get the edited content edited_text = original_text.replace(old_str, new_str) edited_lines = edited_text.split("\n") # Calculate the start and end line numbers for the snippet start_line = max(0, replacement_line - context_lines) end_line = min( len(edited_lines), replacement_line + context_lines + len(new_str.split("\n")), ) # Extract the snippet lines snippet_lines = edited_lines[start_line:end_line] # Format with line numbers result = [] for i, line in enumerate(snippet_lines): line_num = start_line + i + 1 result.append(f"{line_num:4d} | {line}") return "\n".join(result) def truncate_output_content(content: str, prefer_end: bool = True) -> str: """Truncate command output content to a reasonable size. When prefer_end is True, this function prioritizes keeping content from the end of the output, showing some initial context and truncating the middle portion if necessary. Args: content: The command output content to truncate prefer_end: Whether to prefer keeping content from the end of the output Returns: The truncated content with appropriate indicators """ if not content: return content lines = content.splitlines() total_lines = len(lines) # If number of lines is within the limit, check individual line lengths if total_lines <= MAX_LINES_TO_READ: # Process line lengths processed_lines = [] for line in lines: if len(line) > MAX_LINE_LENGTH: processed_lines.append(line[:MAX_LINE_LENGTH] + "... (line truncated)") else: processed_lines.append(line) return "\n".join(processed_lines) # We need to truncate lines, decide based on preference if prefer_end: # Keep some lines from the start and prioritize the end start_lines = lines[:START_CONTEXT_LINES] # Calculate how many lines we can keep from the end end_lines_count = MAX_LINES_TO_READ - START_CONTEXT_LINES end_lines = lines[-end_lines_count:] truncated_content = ( "\n".join(start_lines) + f"\n\n... (output truncated, {total_lines - START_CONTEXT_LINES - end_lines_count} lines omitted) ...\n\n" + "\n".join(end_lines) ) else: # Standard truncation from the beginning (similar to read_file_content) truncated_content = "\n".join(lines[:MAX_LINES_TO_READ]) if total_lines > MAX_LINES_TO_READ: truncated_content += f"\n... (output truncated, showing {MAX_LINES_TO_READ} of {total_lines} lines)" return truncated_content