Deskaid
by ezyang
- 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