Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 6 additions & 24 deletions codemcp/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,17 +267,12 @@ async def codemcp(
raise ValueError("path is required for Grep subtool")

try:
grep_result = await grep_files(
result_string = await grep_files(
pattern, path, include, chat_id, commit_hash
)
result_string = grep_result.get(
"resultForAssistant",
f"Found {grep_result.get('numFiles', 0)} file(s)",
)
return result_string
except Exception as e:
# Log the error but don't suppress it - let it propagate
logging.error(f"Exception in grep subtool: {e!s}", exc_info=True)
logging.error(f"Error in Grep subtool: {e}", exc_info=True)
raise

if subtool == "Glob":
Expand All @@ -287,22 +282,12 @@ async def codemcp(
raise ValueError("path is required for Glob subtool")

try:
glob_result = await glob_files(
pattern,
path,
limit,
offset,
chat_id,
commit_hash,
)
result_string = glob_result.get(
"resultForAssistant",
f"Found {glob_result.get('numFiles', 0)} file(s)",
result_string = await glob_files(
pattern, path, limit, offset, chat_id, commit_hash
)
return result_string
except Exception as e:
# Log the error but don't suppress it - let it propagate
logging.error(f"Exception in glob subtool: {e!s}", exc_info=True)
logging.error(f"Error in Glob subtool: {e}", exc_info=True)
raise

if subtool == "RM":
Expand Down Expand Up @@ -350,10 +335,7 @@ async def codemcp(
if chat_id is None:
raise ValueError("chat_id is required for Chmod subtool")

chmod_result = await chmod(path, mode, chat_id, commit_hash)
result_string = chmod_result.get(
"resultForAssistant", "Chmod operation completed"
)
result_string = await chmod(path, mode, chat_id, commit_hash)
return result_string

except Exception:
Expand Down
44 changes: 15 additions & 29 deletions codemcp/tools/chmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@

async def chmod(
path: str,
mode: str, # Changed from Literal["a+x", "a-x"] to str to handle validation internally
mode: str,
chat_id: str | None = None,
commit_hash: str | None = None,
) -> dict[str, Any]:
) -> str:
"""Change file permissions using chmod.

Args:
path: The absolute path to the file to modify
path: The path to the file to change permissions for
mode: The chmod mode to apply, only "a+x" and "a-x" are supported
chat_id: The unique ID of the current chat session
commit_hash: Optional Git commit hash for version tracking

Returns:
A dictionary with chmod output
A formatted string with the chmod operation result
"""
# Set default values
chat_id = "" if chat_id is None else chat_id
Expand Down Expand Up @@ -73,26 +73,14 @@ async def chmod(

if mode == "a+x" and is_executable:
message = f"File '{path}' is already executable"
result = {
"output": message,
"resultForAssistant": message,
}
# Append commit hash
result["resultForAssistant"], _ = await append_commit_hash(
result["resultForAssistant"], directory
)
return result
message, _ = await append_commit_hash(message, directory, commit_hash)
return message
elif mode == "a-x" and not is_executable:
message = f"File '{path}' is already non-executable"
result = {
"output": message,
"resultForAssistant": message,
}
# Append commit hash
result["resultForAssistant"], _ = await append_commit_hash(
result["resultForAssistant"], directory
)
return result
message, _ = await append_commit_hash(message, directory, commit_hash)
return message

# Execute chmod command
cmd = ["chmod", mode, absolute_path]
Expand Down Expand Up @@ -124,20 +112,18 @@ async def chmod(
if not success:
raise RuntimeError(f"Failed to commit chmod changes: {commit_message}")

# Prepare output
output = {
"output": f"{action_msg} and committed changes",
}
# Prepare result string
result_string = f"{action_msg} and committed changes"

# Add formatted result for assistant
output["resultForAssistant"] = render_result_for_assistant(output)
# Format the result for assistant
formatted_result = render_result_for_assistant({"output": result_string})

# Append commit hash
output["resultForAssistant"], _ = await append_commit_hash(
output["resultForAssistant"], directory
formatted_result, _ = await append_commit_hash(
formatted_result, directory, commit_hash
)

return output
return formatted_result


def render_result_for_assistant(output: dict[str, Any]) -> str:
Expand Down
26 changes: 6 additions & 20 deletions codemcp/tools/glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ async def glob_files(
offset: int | None = None,
chat_id: str | None = None,
commit_hash: str | None = None,
) -> Dict[str, Any]:
) -> str:
"""Search for files matching a glob pattern.

Args:
Expand All @@ -162,7 +162,7 @@ async def glob_files(
commit_hash: Optional Git commit hash for version tracking

Returns:
A dictionary with matched files
A formatted string with the search results

"""
try:
Expand All @@ -185,26 +185,12 @@ async def glob_files(
formatted_result, _ = await append_commit_hash(
formatted_result, normalized_path, commit_hash
)
result["resultForAssistant"] = formatted_result

return result
return formatted_result
except Exception as e:
# Log the error
logging.error(f"Error in glob_files: {e}", exc_info=True)

# Prepare error output
error_output = {
"files": [],
"numFiles": 0,
"totalFiles": 0,
"pattern": pattern,
"path": path,
"limit": limit,
"offset": offset,
"error": str(e),
}

# Add formatted result for assistant
error_output["resultForAssistant"] = f"Error searching for files: {e}"

return error_output
# Return error message
error_message = f"Error searching for files: {e}"
return error_message
28 changes: 7 additions & 21 deletions codemcp/tools/grep.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ async def git_grep(
cwd=absolute_path,
capture_output=True,
text=True,
check=False, # Don't raise exception if git grep doesn't find matches
check=False,
)

# git grep returns exit code 1 when no matches are found, which is normal
Expand Down Expand Up @@ -162,7 +162,7 @@ async def grep_files(
include: str | None = None,
chat_id: str | None = None,
commit_hash: str | None = None,
) -> Dict[str, Any]:
) -> str:
"""Search for a pattern in files within a directory or in a specific file.

Args:
Expand All @@ -173,7 +173,7 @@ async def grep_files(
commit_hash: Optional Git commit hash for version tracking

Returns:
A dictionary with matched files
A formatted string with the search results

"""
try:
Expand Down Expand Up @@ -212,25 +212,11 @@ async def grep_files(
result_for_assistant, normalized_path, commit_hash
)

output["resultForAssistant"] = result_for_assistant

return output
return result_for_assistant
except Exception as e:
# Log the error
logging.error(f"Error in grep_files: {e}", exc_info=True)

# Prepare error output
error_output = {
"numFiles": 0,
"matchedFiles": [],
"truncated": False,
"pattern": pattern,
"path": path,
"include": include,
"error": str(e),
}

# Add formatted result for assistant
error_output["resultForAssistant"] = f"Error searching for pattern: {e}"

return error_output
# Return error message
error_message = f"Error searching for pattern: {e}"
return error_message